2010-12-06 8 views
9

Si alguna vez se preguntó ¿cómo puedo eliminar errores de liberación/cuestiones alloc en Objective-C, se le han encontré con estos valores de entorno que puede ayudar a rastrear el problema abajo:La comprensión de un vertedero malloc_history

  • NSZombieEnabled - Keeps despreciables alrededor después de la liberación, para que pueda obtener punteros etc.
  • MallocStackLogging - mantiene historial del objeto para su posterior consulta
  • NSDebugEnabled

Los configura todos a YES en la sección 'entorno' de la pestaña 'argumentos' en la información 'ejecutables' (se encuentra en el árbol de grupos).


Por lo tanto, Im conseguir este resultado de la consola

MiApl [: 40b] - [CALayer retainCount]: mensaje enviado a ejemplo desasignado 0x4dbb170

luego abra la terminal, mientras que el depurador ha reenviado e ruptura y tipo:

malloc_history 4413 0x4dbb170

A continuación, aparece un gran vertedero de texto, y por lo que yo entiendo la parte importante es la siguiente:

ALLOC 0x4dbb160-0x4dbb171 [size=18]: 
thread_a0375540 |start | main | 
UIApplicationMain | GSEventRun | 
GSEventRunModal | CFRunLoopRunInMode | 
CFRunLoopRunSpecific | __CFRunLoopRun 
| __CFRunLoopDoTimer | 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ 
| __NSFireDelayedPerform | 
-[todoListViewController drillDocumentMenu:] | 
-[documentListViewController drillIntoDocumentWithToDoRecord:] | 
-[documentViewController OpenTodoDocument:OfType:WithPath:] | 
-[documentViewController OpenDocumentOfType:WithPath:] | 
-[documentViewController managePDFDocumentWithPath:] | 
-[PDFDocument loadPDFDocumentWithPath:andTitle:] | 
-[PDFDocument getMetaData] | CGPDFDictionaryApplyFunction | 
ListDictionaryObjects(char const*, 
CGPDFObject*, void*) | NSLog | NSLogv 
| _CFLogvEx | __CFLogCString | 
asl_send | _asl_send_level_message | 
asl_set_query | strdup | malloc | 
malloc_zone_malloc 
FREE 0x4dbb160-0x4dbb171 [size=18]: 
thread_a0375540 |start | main | 
UIApplicationMain | GSEventRun | 
GSEventRunModal | CFRunLoopRunInMode | 
CFRunLoopRunSpecific | __CFRunLoopRun 
| __CFRunLoopDoTimer | 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ 
| __NSFireDelayedPerform | 
-[todoListViewController drillDocumentMenu:] | 
-[documentListViewController drillIntoDocumentWithToDoRecord:] | 
-[documentViewController OpenTodoDocument:OfType:WithPath:] | 
-[documentViewController OpenDocumentOfType:WithPath:] | 
-[documentViewController managePDFDocumentWithPath:] | 
-[PDFDocument loadPDFDocumentWithPath:andTitle:] | 
-[PDFDocument getMetaData] | CGPDFDictionaryApplyFunction | 
ListDictionaryObjects(char const*, 
CGPDFObject*, void*) | NSLog | NSLogv 
| _CFLogvEx | __CFLogCString | 
asl_send | _asl_send_level_message | 
asl_free | free 
ALLOC 0x4dbb170-0x4dbb19f [size=48]: 
thread_a0375540 |start | main | 
UIApplicationMain | GSEventRun | 
GSEventRunModal | CFRunLoopRunInMode | 
CFRunLoopRunSpecific | __CFRunLoopRun 
| __CFRunLoopDoTimer | 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ 
| __NSFireDelayedPerform | 
-[todoListViewController drillDocumentMenu:] | 
-[documentListViewController drillIntoDocumentWithToDoRecord:] | 
-[documentViewController OpenTodoDocument:OfType:WithPath:] | 
-[documentViewController OpenDocumentOfType:WithPath:] | 
-[documentViewController managePDFDocumentWithPath:] | 
-[ScrollViewWithPagingViewController init] | -[UIView init] | 
-[UIScrollView initWithFrame:] | -[UIView initWithFrame:] | UIViewCommonInitWithFrame | -[UIView 
_createLayerWithFrame:] | +[NSObject(NSObject) alloc] | +[NSObject(NSObject) allocWithZone:] | class_createInstance | 
_internal_class_createInstanceFromZone | calloc | malloc_zone_calloc 

Lo que no entiendo es sin embargo si la historia se ALLOC, GRATIS, ALLOC entonces ¿Qué indica el error que fue puesto en libertad (neto 1 alloc)?

o mi comprensión del volcado es incorrecta?


EDIT (fresca Run = diferentes punteros de objeto):

detección del zombi con los instrumentos:

¿Por qué y cómo, hace el recuento de salto retener de 1 a -1?

En cuanto a la traza del zombi, se parece a la cuenta de retención está siendo llamado por: Cuarzo través release_root_if_unused


Editar: Resuelto - Me estaba quitando una vista desde super , luego soltándolo. Solucionado con solo liberarlo.

Respuesta

2

@Kay es correcto; el historial de malloc muestra dos asignaciones en la dirección especificada; uno que ha sido asignado y liberado y otro que todavía está en juego.

Lo que necesita es la traza inversa de la llamada al retainCount en el CALayer que ya ha sido lanzado. Debido a que tiene habilitada la detección de zombies, entre otras cosas de depuración de memoria, puede ser que la desasignación simplemente no se haya realizado &.

Mezclar el historial de malloc con la detección de zombies cambia el comportamiento del tiempo de ejecución significativamente.

Sugiero correr con la detección de zombies en Instruments. Con suerte, eso señalará el problema exacto.

Si no, entonces hay un punto de interrupción que puede establecer para romper cuando se envía un mensaje a un zombie. Establezca ese punto de interrupción y vea dónde se detiene.


OK - así, CoreAnimation está utilizando la cuenta para fines internos conservan (los marcos del sistema se salgan con la suya, aunque es frágil).

Creo que el -1 es un arenque rojo; es probable que los zombies devuelvan 0xFF .... FFFF como el conteo de retención y esto se representa como -1 en Instrumentos.

Siguiente mejor estimación; ya que esto está sucediendo en un temporizador, la liberación excesiva probablemente esté ocurriendo durante la animación. Las capas de CoreAnimation deberían manejar esto correctamente. Hay una sobreexpansión de una vista o un contenedor de capas de animación en el código que está causando que la capa desaparezca prematuramente.

¿Has probado "Build and Analyze"? Desafortunadamente, podría captar la mala administración de una vista en algún lugar.

En cualquier caso y como un experimento, intente retener su (s) vista (s) por un tiempo adicional y vea si eso hace que este problema se detenga. Si lo hace, es decir, al menos, una pista.

(O podría ser un error en los marcos del sistema ... tal vez ... pero dudoso.)

Finalmente, ¿quién demonios llama al retainCount?!?!? En el caso de CoreAnimation, es posible que retainCount se esté utilizando internamente como detalle de implementación.

Sin embargo, si es su código, la ubicación de la llamada zombie debería ser bastante evidente.

+0

Pregunta editada para mostrar los resultados de sus recomendaciones. –

+0

Gracias por su ayuda con esto, rastreó el problema: estaba eliminando una vista de super que tenía una vista secundaria y una capa secundaria (grand), y luego solté la vista después de esto. En cambio, ahora solo lanzo. Solo comenzó a suceder desde que actualicé la aplicación a 4.2 (ipad) - Así que aprendí la lección. Gracias de nuevo. –

0

No soy experto, pero si se echa un vistazo a la primera línea en el bloque 3:

ALLOC 0x4dbb170 -0x4dbb19f [size = 48 ]:

Mientras en las otras dos salidas se asignó y liberó un bloque de memoria de tamaño 18 en 0x4dbb160-0x4dbb171. Supongo que el objeto antiguo fue liberado y hay un nuevo objeto que reside en esta dirección de memoria. Por lo tanto, la instancia anterior en 0x ... b160 ya no es válida.

+0

Pensé que el tamaño podría haber sido un indicador. La identificación de un objeto es la dirección de inicio, por lo que el objeto asignado en el bloque 3 es el que causa mis problemas (dado que su dirección de inicio es el objeto informado en la consola). –

+0

Lo que no entiendo es que se muestra claramente aquí está asignado. pero el error indica que se ha liberado ... –

+1

Tiene razón, esperaría una 4ta entrada en el historial de malloc que indique una gratis para b170. ¿Tal vez el puntero a la memoria en sí se ha corrompido? ¿Habilita "Detener en excepciones de Obj-C" en el menú Ejecutar? Hay un sitio web que he marcado hace algún tiempo http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html. Quizás encuentres algunos consejos por allí. – Kay