¿Rompe EXC_BAD_ACCESS en XCode?

Soy nuevo en el desarrollo de iPhone y XCode en general y no tengo idea de cómo comenzar a solucionar problemas de una señal EXC_BAD_ACCESS . ¿Cómo puedo hacer que XCode se rompa en la línea exacta que está causando el error?


Parece que no puedo hacer que XCode se detenga en la línea que causa el problema, pero sí veo las siguientes líneas en mi consola de depuración:

Dom 25 de octubre 15:12:14 jasonsmacbook TestProject [1289]: CGContextSetStrokeColorWithColor: contexto no válido

Dom 25 de octubre 15:12:14 jasonsmacbook TestProject [1289]: CGContextSetLineWidth: contexto no válido

Dom 25 de octubre 15:12:14 jasonsmacbook TestProject [1289]: CGContextAddPath: contexto no válido

Dom 25 de octubre 15:12:14 jasonsmacbook TestProject [1289]: CGContextDrawPath: contexto no válido

2009-10-25 15: 12: 14.680 LanderTest [1289: 207] *** – [CFArray objectAtIndex:]: mensaje enviado a la instancia desasignada 0x3c4e610

Ahora, bash dibujar en el contexto que recupero de UIGraphicsGetCurrentContext() y pasar al objeto con el que quiero dibujar.


Depuración adicional de prueba y error, y descubrí que un NSMutableArray que tengo una propiedad en mi clase era un zombie. Ingresé a la función init para la clase y aquí está el código que estaba usando:

 if ((self = [super init])) { NSMutableArray *array = [NSMutableArray array]; self.terrainBlocks = array; [array release]; } return self; } 

EXC_BAD_ACCESS la línea [array release] y ya no me da la señal EXC_BAD_ACCESS , pero ahora estoy confundido acerca de por qué esto funciona. Pensé que cuando utilicé la propiedad, automáticamente la retuve para mí, y por lo tanto debería liberarla desde dentro de init para que no tenga una fuga. Estoy completamente confundido acerca de cómo funciona esto y todas las guías y preguntas de Stackoverflow que he leído solo me confunden más sobre cómo establecer las propiedades dentro de mi método init. Parece que no hay consenso sobre cuál es la mejor manera.

Para cualquier error EXC_BAD_ACCESS, generalmente está intentando enviar un mensaje a un objeto liberado. La MEJOR manera de seguir estos pasos es usar NSZombieEnabled .

Esto funciona al nunca liberar realmente un objeto, sino envolviéndolo como un “zombie” y colocando una bandera dentro de él que dice que normalmente habría sido liberado. De esta manera, si intenta acceder de nuevo, todavía sabe lo que era antes de cometer el error, y con este poco de información, por lo general, puede retroceder para ver cuál era el problema.

Especialmente ayuda en los subprocesos de fondo cuando el depurador a veces genera información útil.

MUY IMPORTANTE DE NOTA , sin embargo, es que necesita 100% asegurarse de que esto esté solo en su código de depuración y no en su código de distribución. Como nunca se lanza nada, su aplicación se fugará y tendrá fugas. Para recordarme que haga esto, puse este registro en mi appdelegate:

 if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled")) NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!"); 

Si necesita ayuda para encontrar la línea exacta, ejecute Build-and-Debug ( CMD-Y ) en lugar de Build-and-Run ( CMD-R ). Cuando la aplicación falla, el depurador le mostrará exactamente qué línea y, en combinación con NSZombieEnabled, debería poder averiguar exactamente por qué.

Acerca de tu matriz. La línea

 NSMutableArray *array = [NSMutableArray array]; 

en realidad no le proporciona un objeto retenido sino un objeto de liberación automática. Probablemente sea retenido en la línea siguiente, pero luego no deberías lanzarlo en la tercera línea. Mira esto

Esta es la regla fundamental:

Usted toma posesión de un objeto si lo crea usando un método cuyo nombre comienza con “alloc” o “new” o contiene “copy” (por ejemplo, alloc, newObject o mutableCopy), o si le envía un mensaje de retención. Usted es responsable de renunciar a la propiedad de los objetos que posee mediante el lanzamiento o la liberación automática. En cualquier otro momento que reciba un objeto, no debe liberarlo.

En Xcode 4, puede habilitar Zombies haciendo clic en el menú desplegable Scheme (arriba a la izquierda, justo al lado del botón de detener) -> Editar esquema -> Pestaña Diagnóstico -> Activar objetos Zombie

Xcode / gdb siempre se rompe en EXC_BAD_ACCESS , solo necesita subir la stack de llamadas para encontrar el código que lo activó.

Tenga en cuenta que estos tipos de errores a menudo ocurren con objetos autoreleased , lo que significa que la causa última del problema no estará en la stack de llamadas que desencadenó EXC_BAD_ACCESS . Es entonces cuando se vuelven útiles NSZombieEnabled y NSAutoreleaseFreedObjectCheckEnabled.

Una nueva respuesta a un hilo viejo … en XCode 4, la forma más efectiva de diagnosticar excepciones EXC_BAD_ACCESS es usar instrumentos para perfilar su aplicación (desde XCode haga clic en Producto / Perfil y elija Zombies). Esto lo ayudará a identificar los mensajes enviados a los objetos desasignados.

Desde las clases CS193P de Stanford: si agrega un punto de interrupción (manualmente, editando puntos de interrupción) para el símbolo objc_exception_throw , puede obtener una mejor objc_exception_throw de lo que salió mal: dejar que las cosas avancen hasta el punto donde el depurador se detiene tiende a oscurecer las cosas y arruinar el rastro de la stack. Cuando se detiene en objc_exception_throw a menudo puede mirar hacia atrás exactamente a qué acceso / operación causó su problema.

Otro enfoque útil es establecer puntos de interrupción que se dispararán directamente después de que ocurra la excepción:

Abra la ventana de puntos de interrupción (Run – Show – Breakpoints) y agregue dos puntos de interrupción simbólicos llamados “objc_exception_throw” y “[NSException raise]”

De: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

Solo quería agregar para los otros que vienen de una web, buscando soluciones para el mismo error pero con un error diferente. En mi caso, recibí el mismo error cuando intenté crear una instancia de NSDictionary con un error tipográfico en el nombre de la clave donde olvidé agregar “@” al frente de mi clave:

 NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil]; 

Espero no haber perdido una respuesta idéntica, pero he descubierto que es posible que algunos proyectos arrojen este error debido a ejecutarse en simuladores para versiones anteriores de iOS que pueden ser incompatibles con una estructura o dependencia de proyecto. Estuve persiguiendo a uno de estos durante demasiado tiempo antes de darme cuenta de que solo estaba sucediendo en las versiones del simulador de más edad, como iPhone 4S, que ni siquiera se suponía que la aplicación intentara admitir.

Hubiera sido bueno haber recibido un mensaje de error más detallado, pero me imagino que esa es la responsabilidad del marco en el que se originó … En cualquier caso, este es un aterrizaje de búsqueda bastante común y tal vez esto ayudará a alguien que se equivoca tanto. como me encontré a mí mismo.

Antes de habilitar zombies, recomiendo primero deshacerse de todas las advertencias (si tiene alguna). Cosas simples como una función no nula sin return pueden causar este error. Si no tiene advertencias, proceda como sugieren las otras respuestas.