Estoy programando una aplicación en Objective-C y recibo este error:
MyApp (2121,0xb0185000) malloc: *** error para el objeto 0x1068310: doble libre
*** establece un punto de interrupción en malloc_error_break para depurar
Está sucediendo cuando lanzo un NSAutoreleasePool y no puedo averiguar qué objeto estoy lanzando dos veces.
¿Cómo establezco su punto de ruptura?
¿Hay alguna forma de saber qué es este "objeto 0x1068310"?
Respuestas:
Descubrirá cuál es el objeto cuando entre en el depurador. Simplemente busque la pila de llamadas y encontrará dónde la libera. Eso te dirá qué objeto es.
La forma más sencilla de establecer el punto de interrupción es:
fuente
Cuando un objeto se "libera dos veces", la causa más común es que está (innecesariamente) liberando un objeto liberado automáticamente, y luego se libera automáticamente cuando se vacía el grupo de liberación automática que lo contiene.
Descubrí que la mejor manera de rastrear la versión adicional es usar la variable de entorno NSZombieEnabled para el ejecutable afectado en Xcode. Para obtener un resumen rápido de cómo usarlo, consulte esta página wiki de CocoaDev . (Además de esta página, Apple ha documentado algunos consejos increíblemente oscuros pero útiles para depurar código en Xcode, algunos de los cuales me han salvado el tocino más de unas pocas veces. Sugiero consultar esta Nota técnica en developer.apple.com - enlace salta a la sección sobre el marco de Cocoa's Foundation).
Editar: a menudo puede rastrear el objeto ofensivo dentro del depurador de Xcode, pero a menudo es mucho más fácil si usa Instrumentos para ayudarlo. Desde Xcode, elija Ejecutar → Comenzar con la herramienta de rendimiento → Asignaciones de objetos y debería poder rastrear el objeto ofensivo hasta donde se creó. (Esto funcionará mejor si tienes los zombis habilitados como se mencionó anteriormente). Nota: Snow Leopard agrega una herramienta Zombies a los instrumentos, accesible también desde el menú Ejecutar. ¡Podría valer los $ 29 solo! ;-)
También hay una pregunta SO relacionada aquí .
fuente
Solo quiero agregar mi experiencia además de la respuesta de Quinn Taylor.
En una de mis aplicaciones, tengo que analizar y guardar datos en objetos de datos centrales y luego hacer que estos objetos se muestren en las vistas. De hecho, la aplicación funciona bien y no se bloquea en absoluto, hasta que intenté hacer una prueba de esfuerzo de navegar de un lado a otro varias veces, intenté abrir varias vistas lo más rápido posible. La aplicación se bloquea con el mensaje anterior.
Probé todos los métodos que sugirió Quinn en su respuesta y aún no pude averiguar dónde estaba la causa exacta.
Configuré NSZombieEnabled = YES y NSStackLogging = YES, ejecuté el comando shell malloc_history para averiguar por qué, pero aún así no tuve suerte. Siempre señala dónde guardo los datos en objetos de datos centrales, de hecho, he verificado miles de veces los objetos liberados allí, nada extraño.
Ejecutar instrumentos con varias herramientas (asignaciones, fugas, etc.) todavía no ayudó. Habilitar al guardia Malloc todavía no tiene nada.
Rescate final: traté de volver a las vistas donde los objetos se tomaron de Core Data y envié un mensaje de retención a todos estos objetos, y tomé nota de estos cambios. ¡¡¡Resolvió el problema !!!
Entonces, descubrí que no pude retener uno, esa es exactamente la causa. Solo quiero compartir mi experiencia para que tengas otro rescate para tu aplicación.
fuente
Abra la consola del depurador presionando Cmd + Shift + R. Allí, escriba
break malloc_error_break
para establecer un punto de interrupción al comienzo de la
malloc_error_break
función.Si desea averiguar qué objeto se encuentra en la dirección 0x1068310, puede escribir lo siguiente en la consola del depurador:
print-object 0x1068310
Por supuesto, debe hacer esto mientras el objeto aún está vivo; si el objeto ya se ha liberado cuando lo hace, entonces esto no funcionará.
fuente
po
alias, o de manera equivalenteexpr -o
. En los años transcurridos desde que se escribió originalmente esta respuesta, el motor de depuración utilizado por Xcode se ha cambiado de GDB a LLDB, y LLDB tiene un conjunto diferente de comandos.Para mí, el problema fue resuelto por
(gdb) call (void)_CFAutoreleasePoolPrintPools()
justo después del accidente. La dirección en la parte superior de la pila era la dirección del culpable. Lanzó un
retain
y listo.La dirección proporcionada en el mensaje de registro no me llevó a ninguna parte. Nunca apareció en ninguno de los diversos Instrumets. Al parecer, un puntero a algunos datos internos que ya se habían liberado.
fuente
Agregar un punto de interrupción simbólico en Xcode 4
Solo una actualización para que esto sea relevante para Xcode 4 ...
De la Guía del usuario de Xcode 4 :
fuente
Así es como se ve el punto de interrupción malloc_error_break en la ventana Puntos de interrupción en Xcode. Necesito marcar las casillas para que funcione.
texto alternativo http://www.martijnthe.nl/wp-content/uploads/2009/08/Afbeelding-1.png
fuente
Verifique sus clases y busque en el método dealloc. Asegúrate de que te importa llamar
[super dealloc].
Tuve exactamente el mismo problema y descubrí que estaba llamando
[self dealloc]
. Simplemente sin prestar atención.fuente
Encuentre los pasos a continuación sobre cómo encontrar el objeto que está libre y bloquear la aplicación.
O también puede consultar la presentación GIF a continuación.
fuente
Esto suele ser causado por algún inspector, como safari o vista previa de safari. Consulte la publicación o publicación y pregunta .
Elimine la selección de Mostrar Web automáticamente ...., eliminará este problema.
Tenga en cuenta que simplemente cerrar safari o la vista previa de safari no eliminará este problema. Y debe deseleccionar tanto la vista previa de safari como la de safari.
Si esto no funciona, consulte esta respuesta o publique para depurarlo.
fuente
En Xcode, haga clic a la izquierda del número de línea para establecer un punto de interrupción. Luego, puede iniciarlo haciendo un "Compilar y depurar".
Se recomienda no tener ningún objeto que cree,
autorelease
ya que la memoria es una mercancía en el iPhone. Apple recomienda llamar explícitamenterelease
.fuente
Para encontrar este tipo de problemas de memoria y puntero en general, desea ejecutar su código contra un verificador de errores de memoria en tiempo de ejecución como Valgrind . Esto debería poder señalar muchas cosas que su código está haciendo mal, más allá de las que causan que se bloquee.
Valgrind puede funcionar en OSX (aunque dice que "no es compatible, está incompleto y tiene errores"), y con un poco de pirateo, alguien hizo que funcionara en los ejecutables del SDK de iPhone .
Aún mejor, puede probar Instruments, que es parte de XCode. Hay un tutorial para ejecutarlo aquí .
fuente
Si
malloc_error_break
no está ayudando ...La mejor forma de solucionar este error es ejecutar los instrumentos con el
NSZombies
encendido. Los instrumentos te avisarán cuando se envíe un mensaje al Zombie y podrás rastrear directamente la línea de código.Snow Leopard requiere, ¡qué salvavidas!
fuente