2011-10-13 15 views
7

Pasé algún tiempo depurando un problema extraño con ARC y las funciones de destracking personalizadas.Problema de depuración de Xcode y ARC (omisión de dealloc)

  1. estoy subclases NSOperation clase
  2. I conjunto de bloques de terminación para esta operación
  3. La operación es referenciado por una fuerte característica de muy objeto plano (no hay métodos, ivars automáticos, dos propiedades fuertes) llamemos a este objeto DataRequest
  4. siguiendo todas las pautas el bloque de finalización utiliza solo referencias débiles a objetos locales (incluida la operación en sí)
  5. ni compilador ni analizador ge nerar cualquier problema
  6. DataRequest contiene la ÚNICA referencia a la operación que genero y se destruye en el bloque de finalización de la operación. Ha destruido SIEMPRE (su dealloc siempre ejecutado)
  7. Mi operación tiene una costumbre dealloc. Solo tengo una sola llamada NSLog.

... y la cuestión es:

Si me quedo en virtud de este depurador, el punto de interrupción en el dealloc no es golpeado, nunca aparece el mensaje de registro. Principalmente, pensé que la operación estaba goteando.

Si ejecuto esto en instrumentos, todo está bien, la consola del sistema imprime el mensaje y el instrumento Allocations informa que la operación se liberó de la instantánea de la pila adecuada, incluido el destracking personalizado. No se detectaron fugas.

estoy 100% seguro de que utilizar la misma configuración del compilador para la depuración y para el perfilado.

Lo más confuso al final: si creo una versión personalizada de [DataRequest dealloc] y le pongo self.operation = nil;, todo funciona bien incluso desde el depurador.

¿Alguien tiene algunas pistas sobre qué opciones de engarce del compilador para ver la diferencia? puede ser un error en las herramientas de Apple (todos nosotros estábamos en la posición de culpar a un gran pez por nuestros propios errores, ¿verdad?)

... y sí lo he intentado con GDB y LLDB. El resultado fue el mismo, lo que podría indicar algo.

He tratado de crear una muestra minimalista pero sólo funcionó (de hecho);)

Gracias

+0

He hecho una observación muy básica ... si ejecuto la aplicación en el simulador de XCode (GDB o LLDB) mis mensajes de registro en 'dealloc' no se imprimen. Si dejo el depurador y lanzo la aplicación directamente desde el simulador, Console.app muestra todos los mensajes. No hay compilación sin enlaces intermedios. Extraño. – simpleone

+0

... y un resultado aún más sencillo ... Si ejecuto la aplicación desde XCode en una sesión de depuración - dealloc no se llama (registro no impreso) si ejecuto la aplicación manualmente en el simulador y luego adjunto el depurador ... .todo es como se esperaba – simpleone

Respuesta

7

¿Tiene NSZombiesEnabled? Tuvimos el mismo problema y lo "resolvió" al deshabilitar NSZombies.

"producto" -> "Scheme" -> "Editar esquema" -> "Diagnóstico" -> Desactive la opción "Activar zombi Objetos"

no estoy seguro de por qué dealloc no se llama cuando se habilitan NSZombies (Estoy bastante seguro de que se llamó antes de ARC).

+0

Tengo que probar, pero sí, tengo configurado NSZombiesEnabled. Esto parece bastante probable, y al menos da una explicación razonable para un comportamiento diferente. – simpleone

+1

Puedo confirmar que NSZombiesEnabled está causando el problema. ¡Muchas gracias! – simpleone

+1

Esto puede suceder en cualquier lugar cuando se usa NSZombiesEnabled con ARC, no solo con 'NSOperation'. La clave si observar las peculiaridades dealloc con ARC es deshabilitar NSZombiesEnabled (que está etiquetado como "Objetos Zombie Habilitados" en la pestaña Editar Esquemas ...> Diagnóstico en Xcode 4.) –

1

me encontré con el mismo tipo de problema hoy y me llevó cerca de 5 horas para encontrar que el problema fue causado por NSZombies habilitadas en la configuración de mi proyecto.

También estoy de acuerdo que antes de ARC se llamó a dealloc en este caso.

Después de muchas pruebas, parece que no se llama a dealloc si se usa iOS 5.x (dispositivo o simulador).

pero se llamó de nuevo (con Zombies habilitados) en iOS 6.x (o dispositivo simulador)

no sé si este cambio se debe a un error en IOS5 que ha sido parcheado en iOS 6, o una característica introducida y revertida.

Espero que ayude ...

0

me encontré con el mismo tipo de problema hoy, pero mi problema era un ciclo de retener generada por un bloque.

Si está utilizando bloques:

  1. Verificar si el Sí mismo no aparecen en el interior del bloque.
  2. Si necesita usar SELF dentro de un bloque, use una referencia débil.
  3. Asegúrate de que no haya macros dentro del bloque que puedan estar haciendo referencia a uno mismo (como NSAssert).
Cuestiones relacionadas