Pregunta

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 veo las siguientes líneas en mi consola de depuración:

  

Dom 25 de octubre 15:12:14 jasonsmacbook   TestProject [1289]:   CGContextSetStrokeColorWithColor:   contexto invá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   instancia desasignada 0x3c4e610

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


Más depuración de prueba y error y descubrí que un NSMutableArray para el 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;    
}

Eliminé 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 usaba la propiedad, automáticamente la conservaba para mí y, por lo tanto, debería liberarla desde init para que no tuviera 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 propiedades dentro de mi método init. Parece que no hay consenso sobre cuál es la mejor manera.

¿Fue útil?

Solución

Para cualquier error EXC_BAD_ACCESS, generalmente está intentando enviar un mensaje a un objeto liberado. La MEJOR forma de rastrearlos es usando NSZombieEnabled .

Esto funciona nunca liberando realmente un objeto, sino envolviéndolo como un "zombie". y colocando una bandera en su interior que dice que normalmente se habría lanzado. De esta manera, si intenta acceder de nuevo, aún sabrá qué era antes de cometer el error, y con esta pequeña información, generalmente puede retroceder para ver cuál era el problema.

Es especialmente útil en subprocesos en segundo plano cuando el depurador a veces pierde información útil.

MUY IMPORTANTE TENER EN CUENTA sin embargo, es necesario que se asegure al 100% de que esto solo se encuentra en su código de depuración y no en su código de distribución. Como nunca se lanza nada, su aplicación tendrá fugas y fugas y fugas. Para recordarme que haga esto, pongo este registro en mi applelegate:

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

Si necesita ayuda para encontrar la línea exacta, haga una compilación y depuración ( CMD-Y ) en lugar de una compilación y ejecución ( 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é.

Otros consejos

Acerca de su matriz. La línea

NSMutableArray *array = [NSMutableArray array];

en realidad no le da un objeto retenido sino más bien un objeto de liberación automática. Probablemente se retenga en la siguiente línea, pero no debe liberarlo en la tercera línea. Consulte this

  

Esta es la regla fundamental:

     
    

Usted toma posesión de un objeto si lo crea usando un método cuyo nombre comienza con & # 8220; alloc & # 8221; o & # 8220; nuevo & # 8221; o contiene & # 8220; copia & # 8221; (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 Esquema (arriba a la izquierda, justo al lado del botón de detener) - > Editar esquema - > Pestaña Diagnóstico - > Habilitar objetos zombie

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

Tenga en cuenta que este tipo de errores a menudo se producen con objetos autoreleased , lo que significa que la causa final del problema no estará en la pila de llamadas que desencadenó EXC_BAD_ACCESS . Es entonces cuando NSZombieEnabled y NSAutoreleaseFreedObjectCheckEnabled se vuelven útiles.

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

De 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 imagen mucho mejor de lo que salió mal, permitiendo que las cosas continúen hasta el punto donde el depurador se detiene solo tiende a oscurecer las cosas y arruina el rastro de la pila. Cuando se detiene en objc_exception_throw, a menudo puede recordar exactamente qué acceso / operación causó su problema.

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

  

Abra la ventana de puntos de interrupción (Ejecutar & # 8211; Mostrar & # 8211; Puntos de interrupción) y agregue dos puntos de interrupción simbólicos llamados & # 8220; objc_exception_throw & # 8221; y & # 8220; [aumento de excepción NS] "

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 " @ " delante de mi llave:

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 la ejecución de simuladores para versiones anteriores de iOS que pueden ser incompatibles con una dependencia o marco de proyecto. Estuve persiguiendo uno de estos durante demasiado tiempo antes de darme cuenta de que solo estaba sucediendo en las versiones de simulador más antiguas, como el iPhone 4S, que ni siquiera se suponía que la aplicación intentara soportar.

Hubiera sido bueno haber recibido un mensaje de error más detallado, pero me imagino que es responsabilidad del marco donde se originó ... En cualquier caso, este es un aterrizaje de búsqueda bastante común y tal vez esto ayude a alguien a hacer el tonto. tan mal como me encontré.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top