c++ c exc-bad-access

c++ - ¿Cuál es el significado del código de excepción "EXC_I386_GPFLT"?



exc-bad-access (4)

A menudo puede obtener información de los archivos de encabezado. Por ejemplo:

$ cd /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk $ find usr -name /*.h -exec fgrep -l EXC_I386_GPFLT {} /; usr/include/mach/i386/exception.h ^C $ more usr/include/mach/i386/exception.h .... #define EXC_I386_GPFLT 13 /* general protection fault */

OK, entonces es una falla de protección general (como su nombre lo sugiere de todos modos). Google "falla de protección general i386" produce muchos éxitos, pero looks interesante:

La protección de memoria también se implementa utilizando los descriptores de segmento. Primero, el procesador verifica si un valor cargado en un registro de segmento hace referencia a un descriptor válido. Luego verifica que cada dirección lineal calculada en realidad se encuentra dentro del segmento. Además, el tipo de acceso (lectura, escritura o ejecución) se compara con la información en el descriptor de segmento. Cuando una de estas comprobaciones falla, se genera la excepción (interrupción) 13 (hex 0D). Esta excepción se llama falla de protección general (GPF).

Eso 13 coincide con lo que vimos en los archivos de encabezado, por lo que parece lo mismo. Sin embargo, desde el punto de vista del programador de aplicaciones, solo significa que estamos haciendo referencia a la memoria que no deberíamos tener, y realmente no importa cómo se implementa en el hardware.

¿Cuál es el significado del código de excepción EXC_I386_GPFLT ?

¿Su significado varía según la situación?

En ese caso, me refiero al tipo de excepción EXC_BAD_ACCESS con el código de excepción EXC_I386_GPFLT

El programa está desarrollado en Xcode 5.0.1, que trata de cblas_zgemm() de la biblioteca BLAS. (Bueno, supongo que no importa ...)

¡Muchas gracias!


EXC_I386_GPFLT seguramente se refiere a la "falla de protección general", que es la forma del x86 de decirle que "hizo algo que no tiene permitido hacer". Por lo general, NO significa que acceda a límites de memoria insuficiente, pero podría ser que su código se salga de los límites y haga que se utilicen códigos / datos incorrectos de forma que se produzca una violación de protección de algún tipo.

Desafortunadamente, puede ser difícil averiguar exactamente cuál es el problema sin más contexto, hay 27 causas diferentes enumeradas en mi Manual del programador AMD64, Vol. 2 del 2005 - por todas las cuentas, es probable que 8 años más tarde hubiera agregado algunas Más.

Si se trata de un sistema de 64 bits, un escenario plausible es que su código esté utilizando un "puntero no canónico", lo que significa que una dirección de 64 bits está formada de tal forma que los 16 bits superiores de la dirección no son todas las copias de la parte superior de los 48 bits inferiores (en otras palabras, los 16 bits superiores de una dirección deberían ser todos 0 o todos 1, basándose en el bit justo debajo de 16 bits). Esta regla existe para garantizar que la arquitectura pueda "expandir de forma segura el número de bits válidos en el rango de direcciones". Esto indicaría que el código está sobreescribiendo algunos datos del puntero con otras cosas, o saliéndose de los límites al leer algún valor del puntero.

Otra causa probable es el acceso no alineado con un registro SSE; en otras palabras, leer un registro SSE de 16 bytes desde una dirección que no está alineada con 16 bytes.

Hay, como dije, muchas otras razones posibles, pero la mayoría involucra cosas que el código "normal" no estaría haciendo en un sistema operativo de 32 o 64 bits (como cargar registros de segmento con índice de selector no válido o escribir en MSR (registros específicos del modelo)).


Me preguntaba por qué apareció esto durante mis pruebas unitarias.

He agregado una declaración de método a un protocolo que incluye throws ; pero el método de lanzamiento potencial ni siquiera se usó en esa prueba en particular. Habilitar a los Zombies en la prueba sonó como un problema.

Resulta que una limpieza didK hizo el truco. Siempre estoy flabberghasted cuando eso resuelve problemas reales.


Para depurar y encontrar la fuente: habilite Zombies para la aplicación (Product / Scheme) e inicie Instruments, Select Zombies. Ejecute su aplicación en Xcode Luego vaya a Instruments, comience a grabar. Vuelve a tu aplicación y prueba a generar el error. Los instrumentos deben detectar una mala llamada (a zombie) si hay uno.

¡Espero eso ayude!