Se recibió la señal EXC_BAD_ACCESS

Al implementar la aplicación en el dispositivo, el progtwig se cerrará después de algunos ciclos con el siguiente error:

Program received signal: "EXC_BAD_ACCESS". 

El progtwig se ejecuta sin problemas en el simulador de iPhone, también se depurará y ejecutará siempre que siga las instrucciones de a uno por vez. Tan pronto como lo deje funcionar nuevamente, presionaré la señal EXC_BAD_ACCESS .

En este caso particular, resultó ser un error en el código del acelerómetro. No se ejecutaría dentro del simulador, por lo que no arrojó ningún error. Sin embargo, se ejecutaría una vez implementado en el dispositivo.

La mayoría de las respuestas a esta pregunta se refieren al error EXC_BAD_ACCESS general, por lo que lo dejaré abierto como un EXC_BAD_ACCESS para el temido error de acceso erróneo.

EXC_BAD_ACCESS normalmente se lanza como resultado de un acceso a memoria ilegal. Puede encontrar más información en las respuestas a continuación.

¿Ha encontrado la señal EXC_BAD_ACCESS anteriormente, y cómo ha EXC_BAD_ACCESS con ella?

Según su descripción, sospecho que la explicación más probable es que tiene algún error en la administración de su memoria. Dijiste que has estado trabajando en el desarrollo de iPhone durante unas semanas, pero no si tienes experiencia con Objective C en general. Si proviene de otro contexto, puede tomar un poco de tiempo antes de internalizar realmente las reglas de administración de memoria, a menos que tenga un gran punto.

Recuerde, todo lo que obtiene de una función de asignación (generalmente el método de asignación estática, pero hay algunos otros), o un método de copia, también es dueño de la memoria y debe liberarla cuando haya terminado.

Pero si obtiene algo de casi todo lo demás, incluidos los métodos de fábrica (por ejemplo, [NSString stringWithFormat] ), tendrá una referencia de liberación automática, lo que significa que podría ser lanzado en algún momento en el futuro por otro código, por lo que es vital que si necesitas mantenerlo más allá de la función inmediata que lo retienes. Si no lo hace, la memoria puede permanecer asignada mientras la está usando, o puede ser lanzada pero coincidentemente válida, durante la prueba del emulador, pero es más probable que se lance y se muestre como un error de acceso cuando se ejecuta en el dispositivo.

La mejor manera de rastrear estas cosas, y una buena idea de todos modos (incluso si no hay problemas aparentes) es ejecutar la aplicación en la herramienta Instrumentos, especialmente con la opción Fugas.

Una causa importante de EXC_BAD_ACCESS es la de intentar acceder a los objetos liberados.

Para saber cómo resolver este problema, lea este documento: DebuggingAutoReleasePool

Incluso si no cree que está “liberando objetos lanzados automáticamente”, esto se aplicará a usted.

Este método funciona extremadamente bien. ¡Lo uso todo el tiempo con gran éxito!

En resumen, esto explica cómo usar la clase de depuración NSZombie de Cocoa y la herramienta de línea de comandos “malloc_history” para encontrar exactamente a qué objeto liberado se ha accedido en su código.

Nota al margen:

La ejecución de instrumentos y la comprobación de fugas no ayudarán a solucionar los problemas de EXC_BAD_ACCESS. Estoy bastante seguro de que las pérdidas de memoria no tienen nada que ver con EXC_BAD_ACCESS. La definición de fuga es un objeto al que ya no tiene acceso y, por lo tanto, no puede llamarlo.

ACTUALIZACIÓN: ahora uso instrumentos para depurar fugas. Desde Xcode 4.2, elija Product-> Profile y cuando se inicie Instruments, elija “Zombies”.

Una señal EXC_BAD_ACCESS es el resultado de pasar un puntero no válido a una llamada al sistema. Hace poco recibí uno el día de hoy con un progtwig de prueba en OS X: estaba pasando una variable no inicializada a pthread_join() , que se debió a un error tipográfico anterior.

No estoy familiarizado con el desarrollo de iPhone, pero debe verificar dos veces todos los punteros de búfer que está pasando a las llamadas al sistema. Poner en marcha el nivel de advertencia de tu comstackdor hasta el final (con gcc, usa las opciones -Wall y -Wextra ). Habilite tantos diagnósticos en el simulador / depurador como sea posible.

En mi experiencia, esto generalmente es causado por un acceso ilegal a la memoria. Verifique todos los punteros, especialmente los punteros a objetos, para asegurarse de que estén inicializados. Asegúrese de que su archivo MainWindow.xib, si está utilizando uno, esté configurado correctamente, con todas las conexiones necesarias.

Si ninguna de esas comprobaciones en papel da vuelta algo, y no sucede cuando se trata de pasos simples, intente localizar el error con las declaraciones NSLog (): rocíe su código con ellas, moviéndolos hasta que aisle la línea que está causando. el error. Luego establece un punto de interrupción en esa línea y ejecuta tu progtwig. Cuando llegue al punto de interrupción, examine todas las variables y los objetos en ellas, para ver si algo no se parece a lo esperado. Sobre todo, debería estar atento a las variables cuya clase de objetos es algo que no esperaba. Si se supone que una variable contiene una UIWindow pero tiene una NSNotification en su lugar, el mismo error de código subyacente podría manifestarse de una manera diferente cuando el depurador no está en funcionamiento.

Acabo de pasar un par de horas rastreando un EXC_BAD_ACCESS y encontré que NSZombies y otros env vars no parecían decirme nada.

Para mí, fue una statement NSLog estúpida con especificadores de formato, pero no se pasaron argumentos.

 NSLog(@"Some silly log message %@-%@"); 

Arreglado por

 NSLog(@"Some silly log message %@-%@", someObj1, someObj2); 

Los videos de WWDC 2010 están disponibles para todos los participantes en el progtwig para desarrolladores de Apple. Hay un gran video: “Sesión 311 – Análisis avanzado de memoria con instrumentos” que muestra algunos ejemplos del uso de zombies en instrumentos y la depuración de otros problemas de memoria.

Para un enlace a la página de inicio de sesión, haga clic AQUÍ .

No es una respuesta completa, pero una situación específica en la que he recibido esto es cuando trato de acceder a un objeto que ‘murió’ porque traté de usar la liberación automática:

 netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease]; 

Así que, por ejemplo, en realidad estaba pasando esto como un objeto para ‘notificar’ (lo registraba como oyente, observador, cualquier modismo que quisiera) pero ya había muerto una vez que se envió la notificación y obtenía el EXC_BAD_ACCESS. [[MyNetObject alloc] init] a [[MyNetObject alloc] init] y soltarlo más tarde, según corresponda, resolvió el error.

Otra razón por la que esto puede pasar es, por ejemplo, si pasas un objeto e intentas almacenarlo:

 myObjectDefinedInHeader = aParameterObjectPassedIn; 

Más tarde, cuando intenta acceder a myObjectDefinedInHeader, puede tener problemas. Utilizando:

 myObjectDefinedInHeader = [aParameterObjectPassedIn retain]; 

puede ser lo que necesitas Por supuesto, estos son solo un par de ejemplos de lo que me he encontrado y existen otros motivos, pero estos pueden ser difíciles de encontrar, así que los menciono. ¡Buena suerte!

Solo para agregar otra situación donde esto puede suceder:

Tenía el código:

 NSMutableString *string; [string appendWithFormat:@"foo"]; 

Obviamente, había olvidado asignar memoria para la cadena:

 NSMutableString *string = [[NSMutableString alloc] init]; [string appendWithFormat:@"foo"]; 

arregla el problema

Otro método para detectar excepciones EXC_BAD_ACCESS antes de que sucedan es el analizador estático , en XCode 4+.

Ejecute el analizador estático con Producto> Analizar (shift + cmd + B). Al hacer clic en cualquier mensaje generado por el analizador se superpondrá un diagtwig en su fuente que muestra la secuencia de retenciones / liberaciones del objeto ofensivo.

enter image description here

Me parece útil establecer un punto de interrupción en objc_exception_throw. De esa forma, el depurador debería romperse cuando obtenga el EXC_BAD_ACCESS.

Las instrucciones se pueden encontrar aquí DebuggingTechniques

Use la regla simple de “si no la asignó o retuvo, no la suelte”.

Cómo depurar EXC_BAD_ACCESS

Mira el enlace de arriba y haz lo que dice …. Solo unas instrucciones rápidas para usar NSZombies

Ejecute la aplicación y luego de que falle (debe mostrar “Interrumpido” en lugar de “EXC_BAD_ACCESS” … revise la Consola (Ejecutar> Consola) … debería haber un mensaje allí que indique a qué objeto estaba intentando acceder.

-Ben

He estado depurando y refabricando el código para resolver este error durante las últimas cuatro horas. Una publicación anterior me llevó a ver el problema:

Propiedad antes: startPoint = [[DataPoint alloc] init]; startPoint = [DataPointList objectAtIndex: 0];
. . . x = startPoint.x – 10; // EXC_BAD_ACCESS

Propiedad después de: startPoint = [[DataPoint alloc] init]; startPoint = [[DataPointList objectAtIndex: 0] retener];

Adiós EXC_BAD_ACCESS

Espero que estés liberando la ‘cuerda’ cuando hayas terminado!

Me olvidé de volver a mí mismo en un método de iniciación …;)

Este es un excelente hilo. Aquí está mi experiencia: cometí un error con la palabra clave retain / assign en una statement de propiedad. Dije:

 @property (nonatomic, assign) IBOutlet UISegmentedControl *choicesControl; @property (nonatomic, assign) IBOutlet UISwitch *africaSwitch; @property (nonatomic, assign) IBOutlet UISwitch *asiaSwitch; 

donde debería haber dicho

 @property (nonatomic, retain) IBOutlet UISegmentedControl *choicesControl; @property (nonatomic, retain) IBOutlet UISwitch *africaSwitch; @property (nonatomic, retain) IBOutlet UISwitch *asiaSwitch; 

Me encontré con EXC_BAD_ACCESS en el iPhone solo mientras trataba de ejecutar un método C que incluía una gran matriz. El simulador fue capaz de darme suficiente memoria para ejecutar el código, pero no el dispositivo (¡la matriz tenía un millón de caracteres, por lo que era un poco excesiva!).

El EXC_BAD_ACCESS ocurrió justo después del punto de entrada del método, y me confundió por bastante tiempo porque no estaba ni cerca de la statement del arreglo.

Tal vez alguien más podría beneficiarse de mi par de horas de tirar el cabello.

Se olvidó de sacar un puntero no asignado de dealloc . Obtenía el exc_bad_access en mi rootView de un UINavigationController, pero solo algunas veces. Supuse que el problema estaba en el rootView porque se estaba colgando a la mitad de su viewDidAppear {}. Resultó que solo sucedió después de que apareció la vista con el lanzamiento malo dealloc {}, ¡y eso fue todo!

“EXC_BAD_ACCESS” [Cambiando al proceso 330] No hay memoria disponible para progtwigr ahora: no es seguro llamar a malloc

Pensé que era un problema donde estaba tratando de asignar … no donde estaba tratando de lanzar un no-alloc, ¡oh!

Cómo trato con EXC_BAD_ACCESS

A veces siento que cuando se lanza un error EXC_BAD_ACCESS, xcode mostrará el error en la clase main.m, sin dar información adicional sobre dónde ocurre el locking (a veces).

En esos momentos podemos establecer un Punto de Inflexión Excepcional en Xcode para que cuando se capture la excepción, se establezca un punto de interrupción e intimará directamente al usuario que el accidente ocurrió en esa línea.

enter image description here

Las llamadas NSAssert () para validar los parámetros del método son bastante útiles para rastrear y evitar pasar nils también.

acabo de tener este problema. Para mí, el motivo fue eliminar un objeto gestionado CoreData y tratar de leerlo después desde otro lugar.

He estado depurando y refabricando el código para resolver este error durante las últimas cuatro horas. Una publicación anterior me llevó a ver el problema:

Propiedad antes:

 startPoint = [[DataPoint alloc] init] ; startPoint= [DataPointList objectAtIndex: 0]; x = startPoint.x - 10; // EXC_BAD_ACCESS 

Propiedad después:

 startPoint = [[DataPoint alloc] init] ; startPoint = [[DataPointList objectAtIndex: 0] retain]; 

Adiós EXC_BAD_ACCESS

Muchas gracias por tu respuesta. He estado luchando con este problema todo el día. ¡Eres increíble!

Solo para agregar

Lynda.com tiene un fantástico DVD llamado

Entrenamiento esencial de iPhone SDK

y el Capítulo 6, Lección 3 se trata de EXEC_BAD_ACCESS y de trabajar con Zombies.

Fue genial para mí entender, no solo el código de error, sino cómo puedo usar Zombies para obtener más información sobre el objeto liberado.

Para verificar cuál puede ser el error

Use NSZombieEnabled.

Para activar el recurso NSZombieEnabled en su aplicación:

Elija Proyecto> Editar ejecutable activo para abrir la ventana de información ejecutable. Haga clic en Argumentos. Haga clic en el botón Agregar (+) en la sección “Variables para establecer en el entorno”. Ingrese NSZombieEnabled en la columna Nombre y SÍ en la columna Valor. Asegúrese de que la marca de verificación para la entrada NSZombieEnabled esté seleccionada.

Encontré esta respuesta en iPhoneSDK

Me di cuenta de que esto fue preguntado hace un tiempo, pero después de leer este hilo, encontré la solución para XCode 4.2: Producto -> Editar esquema -> Pestaña Diagnóstico -> Activar objetos Zombie

Me ayudó a encontrar un mensaje enviado a un objeto desasignado.

Cuando tienes recursión infinita, creo que también puedes tener este error. Este fue un caso para mí.

Incluso otra posibilidad: al usar bloques en colas, podría suceder fácilmente que intente acceder a un objeto en otra cola, que ya se haya desasignado en este momento. Normalmente, cuando intenta enviar algo a la GUI. Si su punto de interrupción de excepción se establece en un lugar extraño, entonces esta podría ser la causa.

Lo obtuve porque no estaba usando [self performSegueWithIdentifier:sender:] y -(void) prepareForSegue:(UIstoryboardSegue *) right

No olvide el símbolo @ al crear cadenas, tratando C-strings ya que NSStrings causará EXC_BAD_ACCESS .

Utilizar esta:

 @"Some String" 

En vez de esto:

 "Some String" 

PD: generalmente cuando se completan los contenidos de una array con muchos registros.

XCode 4 y superior, se ha hecho realmente simple con Instruments. Solo ejecuta Zombies en Instrumentos. Este tutorial lo explica bien: depuración exc_bad_access error xcode instruments