11

Lo básico es que tengo un NSURLProtocol personalizado. En startLoading, [self client] es de tipo:Cómo evitar el desbordamiento de recuento de referencias en _NSCFURLProtocolBridge en NSURLProtocolo personalizado en el entorno de GC

<_NSCFURLProtocolBridge> {NSURLProtocol, CFURLProtocol} 

El problema se está ejecutando esto en un ambiente de recolección de basura. Debido a que estoy escribiendo un salvapantallas, me veo obligado a hacerlo recolectar basura. Sin embargo, el protocolo _NSCFURLProtocolBridge parece siempre tirar:

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

Un ejemplo de volcado para la consola de depuración es:

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.

Se puede ver que el underflow ocurre para <_NSCFURLProtocolBridge 0x20025ab00>.

Cuando romper el auto_refcount_underflow_error, parece que apilar-rastreo hacia atrás hasta URLProtocolDidFinishLoading: en:

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

Este problema parece haber existido durante un tiempo, pero no parece haber ninguna respuesta en línea:

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

El fallo sólo se manifiesta en los entornos de basura-recogida para estos fallos en la lista así. ¿Alguna idea sobre cómo puedo evitar esto sin causar problemas de memoria? Supongo que esto probablemente tiene algo que ver con el tipo CF debajo de NSURLProtocol que se lanzó incorrectamente.

+0

Una imagen de la traza de la pila: http://img.skitch.com/20090711-qbt4s4jq87jk4g68iaawe7h1hg.png –

Respuesta

4

Última WWDC confirmamos este error con un ingeniero de webkit, él podía ver el error ahí mismo en el código, así que con suerte lo arreglarán. La solución alternativa es CFRetain el cliente en el método 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

Este error generalmente indica que un objeto se retuvo con -retain, pero se liberó con CFRelease(). Si crees que este no podría ser tu objetivo (y eso no es una creencia terrible), entonces deberías abrir otro Radar. Pero primero debe mirar alrededor y ver si hay un objeto CF en el que está usando -retain cuando quizás debería usar CFRetain().

El resto de este se toma la fotografía en la oscuridad ....

Es posible hacerse una idea mediante la intensificación de la pila y mirando a los parámetros que se están pasando a estos métodos ++ C (o sobre todo) auto_zone_release. Pruebe esto en GDB para tratar de ver lo que hay en el primer parámetro:

p *($esp) 

Y ver si puede obtener alguna idea sobre el objeto que se pasa. Tal vez esto funcionará si tiene suerte:

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

Rob - en un entorno GC, están llamadas no -retain NOOPs? Creo que esto es un error y abriré un error de Radar al respecto. ¡Gracias! –

+1

-retain es un NOOP en GC, pero CFRetain() no lo es. Entonces, si llama -retain y luego CFRelease(), se desequilibrará. –

3

Es un error en la implementación de _NSCFURLProtocolBridge.

Utilice http://bugreport.apple.com/ y presente un error. Si incluye la URL a esta página, eso sería apreciado (y si actualiza esta página con el número de radar, eso sería apreciado también). Idealmente, si puede adjuntar un binario de su salvapantallas, sería muy útil; no se necesita fuente

Afortunadamente, no debería causar un bloqueo. Desafortunadamente, probablemente causa una fuga.

1

trabajé en torno a este tema por CFRetain -ing el cliente, y CFRelease -ing de nuevo en la siguiente llamada a startLoading

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

y, por supuesto, en la finalización

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

es una variable de instancia de la subclase NSURLProtocol.

1

Aquí está el informe de error que había presentado hace un tiempo:

http://openradar.appspot.com/8087384

Probablemente la pena presentar así, ya han pasado DUP-ed, pero sería bueno que te lo arreglen.

Como dijo Alex, un desarrollador de Apple miró el código fuente que tenía delante y localizó el problema fácilmente con el ejemplo que teníamos.

+0

Este error se cerró como un engaño de rdar: // 8070298, que parece estar corregido en Lion. –

0

el mismo error aparece a veces usando NSURL en el filtro de diálogo Abrir. para mí fue suficiente para establecerlo en cero explícitamente después de que ya no lo necesite.

Cuestiones relacionadas