2010-05-15 14 views
10

Me estoy salpicado de¿Cómo romper el __NSAutoreleaseNoPool

*** __NSAutoreleaseNoPool(): Objeto de la clase 0x1961180 NSEvent autoreleased sin piscina en su lugar - sólo fugas

advertencias durante la ejecución -tiempo y no tengo idea de cuál es la causa. Cursory Googles indica que este es un símbolo que puedo romper con Xcode, pero agregarlo como un punto de corte simbólico a través de Ejecutar> Gestionar puntos de interrupción> Agregar punto de corte simbólico o simplemente a través de la ventana de administración de puntos de interrupción, da como resultado un punto de interrupción con un - al lado en lugar de un cheque, que interpreto como un símbolo que no se puede encontrar.

He intentado agregar el símbolo "__NSAutoreleaseNoPool" con dos guiones bajos, un guión bajo, y ahora me siento estúpido. Los errores continúan registrándose y no se golpean los puntos de interrupción. Se agradecerá cualquier sugerencia para romper los símbolos de Obj-C o depurar esto. [EDIT: después de tal vez 10 (10 más, un par de docenas en total, incluyendo al menos dos reinicios de Xcode) ejecuta Obtuve el punto de interrupción 9 - "__NSAutoreleasePool" resuelto "impreso en mi consola y el punto de interrupción comenzó a funcionar. ¿Hay alguna manera de forzar a un punto de interrupción pendiente para que lo resuelva realmente?]

Respuesta

1

El problema aquí es simple: está liberando sin un grupo en su lugar. Esto generalmente ocurre en las herramientas de línea de comandos escritas contra Foundation. Basta con añadir el siguiente código a su main(): (partes irrelevantes omitidas)

int main (…) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    /// Your code goes here. 

    [pool drain]; // This one might not strictly speaking be neccessary. 
    [pool release]; 

    return 0; 
} 

Editar: Si no está creando una herramienta de línea de comandos, lo más probable es que usted está haciendo algo malo; pero no obstante: si tiene un código que invoque antes de NSApplicationMain(), debe envolverlo en el mismo código básico, agotando y liberando el grupo antes de la invocación de NSApplicationMain.

+1

más probable que un nuevo hilo con performSelectorInBackground –

+0

Si bien mi pregunta original tenía más que ver con los puntos de interrupción, todavía estoy enredado en esto, también. Ahora que realmente me estoy rompiendo, veo la siguiente pila, y como pueden ver, tengo un pool de autodescripción alrededor de mi NSApplicationMain y sigo recibiendo errores NSNoAutoreleasePool en tiempo de ejecución, sin que se ejecute ninguno de mis códigos (fuera de la principal) : http://not-included.net/gfx/stupid/NSNoAutoReleasePool.png Un lado de la piscina de liberación automática: ¿por qué es esto necesario? ¿No debería manejar esto el grupo de autodesbloque del ciclo de ejecución principal? – Tyrus

+0

Otra ruta de exploración, esto también se imprime después de cada error "sin agrupación en el lugar". Revertido cualquier cambio reciente, y aún aparece; Supongo que no me di cuenta antes: > *** intento de hacer estallar una piscina desconocido autorelease (0x89ac00) – Tyrus

2

Parece que estás usando Cocoa en una hebra en alguna parte y no está envolviendo el cuerpo de la hebra con un grupo de autorrelease. Probablemente no necesite usar puntos de interrupción para encontrar esto. ¿Estás haciendo algún detachNewThreadSelector?

+0

Los puntos de corte se inició a trabajar con el tiempo (y la casilla sin marcar fueron "símbolos de carga perezosa" después de esta terrible experiencia ... Es algo que olvido con cada nueva instalación; me gustaría que no era el valor por defecto). La cuestión parece ser más que la biblioteca de gráficos que estoy usando (SFML) comienza su propio bucle de ejecución en el interior de mi bucle de ejecución existente cuando llamo su sorteo y actualización de las llamadas de un temporizador (hacer esto, así que no cuadra elementos de UI nativos). Esto confunde a Cocoa y la depuración, pero el uso de mi memoria no está explotando como esperaba, así que quizás esto sea algo de lo que me puedo salir con esto (herramienta de desarrollo interno). – Tyrus

+0

Esto me solucionó el problema. Dentro del método (selector) al que estaba llamando con performSelectorInBackground tuve que envolver el cuerpo en un NSAutoreleasePool. –

5

Tengo el mismo problema al configurar el punto de interrupción en __NSAutoreleaseNoPool(). Finalmente establecí con éxito el comando break point use gdb. Después de que se haya iniciado el depurador, presione ctrl + C en la consola del depurador. Utilice "br __NSAutoreleaseNoPool" para establecer el punto de interrupción y reiniciar el depurador.

25

Para responder realmente a su pregunta, busque en NSDebug.h. Allí podrá encontrar un comentario de los cuales esto es parte:

NAME OF ENV. VARIABLE     DEFAULT SET TO... 
NSDebugEnabled       NO "YES" 
NSZombieEnabled       NO "YES" 
NSDeallocateZombies      NO "YES" 
NSHangOnUncaughtException     NO "YES" 

y más abajo son estos comentarios:

// Functions used as interesting breakpoints in a debugger 
// void __NSAutoreleaseNoPool(void *object); 
     // Called to log the "Object X of class Y autoreleased with no 
     // pool in place - just leaking" message. If an environment 
     // variable named "NSAutoreleaseHaltOnNoPool" is set with string 
     // value "YES", the function will automatically break in the 
     // debugger (or terminate the process). 

// void __NSAutoreleaseFreedObject(void *freedObject); 
     // Called when a previously freed object would be released 
     // by an autorelease pool. If an environment variable named 
     // "NSAutoreleaseHaltOnFreedObject" is set with string value 
     // "YES", the function will automatically break in the debugger 
     // (or terminate the process). 

Así que realmente no necesita para establecer estos puntos de ruptura; solo establece las variables de entorno apropiadas. Puedes hacer esto último desde tu p. Ej. .bashrc o en Xcode 4 puede editar la sección "Ejecutar" de su "esquema" y configurarlos allí; eso es lo que hago, y funciona muy bien.

+1

Encuentro más útil dejar NSDeallocateZombies en NO. De lo contrario, se desasignan! Y luego no pueden cumplir su función de colgar para ser zombies. Configurarlo en SÍ es una especie de parche temporal si se está quedando sin memoria. –

0

Sé que este es un hilo viejo. Solo quería compartir algo de luz sobre la solución correcta. La forma correcta de tener un punto de interrupción en _autoreleasenopool es usar el navegador de punto de interrupción en xcode. (Use el comando de teclado + 6). En la parte inferior izquierda del navegador de punto de interrupción, haga clic en el signo '+' y agregue punto de referencia simbólico. Ingrese el símbolo como objc_autoreleaseNoPool.