11

Le informazioni di base sono le NSURLProtocol personalizzate. In startLoading, [self client] è di tipo:Come evitare l'underflow del conteggio dei riferimenti in _NSCFURLProtocolBridge in NSURLProtocol personalizzato in ambiente GC

<_NSCFURLProtocolBridge> {NSURLProtocol, CFURLProtocol} 

Il problema è in esecuzione questo in un ambiente garbage collection. Perché sto scrivendo uno screensaver, sono costretto a renderlo garbage-collected. Tuttavia, il protocollo _NSCFURLProtocolBridge sembra gettare sempre:

malloc: reference count underflow for (memory_id_here), break on auto_refcount_underflow_error to debug

Un esempio discarica alla console di debug è:

ScreenSaverEngine[1678:6807] client is <_NSCFURLProtocolBridge 0x20025ab00> {NSURLProtocol 0x200258ec0, CFURLProtocol 0x20029c400} ScreenSaverEngine(1678,0x102eda000) malloc: reference count underflow for 0x20025ab00, break on auto_refcount_underflow_error to debug.

Si può vedere che l'underflow si verifica per <_NSCFURLProtocolBridge 0x20025ab00>.

Quando rompo il auto_refcount_underflow_error, sembra per impilare-trace di nuovo fino a URLProtocolDidFinishLoading: in:

id client = [self client]; 
... 
[client URLProtocolDidFinishLoading:self]; 

Questo problema sembra essere esistito per un po ', ma non sembra esserci nessuna risposta a tutti on-line:

http://lists.apple.com/archives/cocoa-dev/2008/May/msg01272.html http://www.cocoabuilder.com/archive/message/cocoa/2007/12/17/195056

Il bug si manifesta solo in ambienti garbage collection per questi bug elencati pure. Qualche idea su come posso aggirare questo senza causare problemi di memoria? Presumo che questo probabilmente ha qualcosa a che fare con il tipo di CF sotto NSURLProtocol che viene rilasciato in modo improprio?

+0

Un'immagine della traccia dello stack: http://img.skitch.com/20090711-qbt4s4jq87jk4g68iaawe7h1hg.png –

risposta

4

scorso WWDC abbiamo confermato questo bug con un ingegnere webkit, poteva vedere il bug proprio lì nel codice in modo si spera faranno risolvere il problema. La soluzione alternativa consiste nel CFRetain il client nel metodo initWithRequest.

- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id <NSURLProtocolClient>)client 
{ 
    // work around for NSURLProtocol bug 
    // note that this leaks! 
    CFRetain(client); 

    if (self = [super initWithRequest:request cachedResponse:cachedResponse client:client]) 
    { 
    } 

    return self; 
} 
1

Questo errore indica generalmente che un oggetto è stato mantenuto con -retain, ma rilasciato con CFRelease(). Se credi che questo non possa essere il tuo oggetto (e questa non è una credenza terribile), allora dovresti aprire un altro Radar. Ma dovresti prima guardarti intorno e vedere se c'è un oggetto CF che stai usando quando forse dovresti usare CFRetain().

Il resto di questo sta sparando nel buio ....

Si può guadagnare una certa comprensione accelerando lo stack e guardando i parametri che vengono passati a questi metodi C++ (o particolarmente auto_zone_release). Prova questo in gdb per cercare di vedere cosa c'è nel primo parametro:

p *($esp) 

e vedere se è possibile ottenere qualsiasi comprensione circa l'oggetto che viene passato. Forse questo funzionerà se siete fortunati:

po (id)(*($esp)) 
+0

Rob - in un ambiente GC, non sono -retain chiamate NOOPs? Penso che questo sia un bug e aprirò un bug Radar su di esso. Grazie! –

+1

-retain è un NOOP in CG, ma CFRetain() non lo è. Quindi se chiami -retain e poi CFRelease(), otterrai uno sbilancio. –

3

Si tratta di un bug nell'implementazione di _NSCFURLProtocolBridge.

Utilizzare http://bugreport.apple.com/ e segnalare un errore. Se si include l'URL di questa pagina, ciò sarebbe apprezzato (e se si aggiorna questa pagina con il Radar #, sarebbe apprezzato anche questo). Idealmente, se puoi allegare un file binario del tuo salvaschermo, sarebbe molto utile; nessuna fonte necessaria

Fortunatamente, non dovrebbe causare un crash. Sfortunatamente, probabilmente causa una perdita.

1

ho lavorato intorno a questo problema CFRetain -ing del cliente, e CFRelease -ing di nuovo sulla prossima chiamata a startLoading

-(void)startLoading 
{ 
     if (client) CFRelease(client); 
     client = [self client]; 
     CFRetain(client); 

e, naturalmente, nella finalizzazione

-(void)finalize 
{ 
    if (client) CFRelease(client); 
    [super finalize]; 
} 

client è una variabile del NSURLProtocol sottoclasse istanza.

1

Ecco la segnalazione di bug che avevo depositato un po 'indietro:

http://openradar.appspot.com/8087384

probabilmente vale la pena di deposito pure, è già stato DUP-ed, ma sarebbe bello per farlo riparare.

Come ha detto Alex, uno sviluppatore Apple ha guardato il codice sorgente di fronte a me e ha individuato facilmente il problema con l'esempio che avevamo.

+0

Questo errore è stato chiuso come dupe di rdar: // 8070298, che sembra essere corretto in Lion. –

0

lo stesso errore viene a volte utilizzando NSURL filtro finestra aperta. Per me è stato abbastanza per impostarlo a zero in modo esplicito dopo non mi serve più.

Problemi correlati