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

117

¿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 EXC_BAD_ACCESSde excepción con código de excepciónEXC_I386_GPFLT

El programa está desarrollado en Xcode 5.0.1, y se ocupa cblas_zgemm()de la biblioteca BLAS (bueno, supongo que no importa ...)

¡Muchas gracias!

Lewen
fuente

Respuestas:

112

EXC_I386_GPFLT seguramente se está refiriendo a "Fallo de protección general", que es la forma en que x86 le dice que "hizo algo que no está autorizado". Por lo general, NO significa que acceda fuera de los límites de la memoria, pero podría ser que su código se salga de los límites y haga que se utilicen códigos / datos incorrectos de una manera que constituya 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 de 2005; según todas las cuentas, es probable que 8 años después se hubieran agregado algunas más.

Si se trata de un sistema de 64 bits, un escenario plausible es que su código esté usando un "puntero no canónico", lo que significa que una dirección de 64 bits se forma de tal manera 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 deben ser todos 0 o todos 1, según el bit justo por debajo de los 16 bits). Esta regla está establecida 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á sobrescribiendo algunos datos de puntero con otras cosas o se sale de los límites al leer algún valor de 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 de ellas involucran 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 un índice de selector no válido o escribir en MSR (registros específicos del modelo)).

Mats Petersson
fuente
24

Para depurar y encontrar la fuente: Habilite Zombies para la aplicación (Producto \ Esquema) y Launch Instruments, Seleccione Zombies. Ejecute su aplicación en Xcode Luego vaya a Instrumentos para comenzar a grabar. Regrese a su aplicación e intente generar el error. Los instrumentos deben detectar una llamada incorrecta (a zombie) si la hay.

¡Espero eso ayude!

Khalid Mammadov
fuente
23

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     */

Bien, entonces es una falla de protección general (como su nombre sugiere de todos modos). Buscar en Google "Falla de protección general de i386" produce muchos resultados, pero esto parece interesante:

La protección de la 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 se encuentre realmente dentro del segmento. Además, el tipo de acceso (lectura, escritura o ejecución) se compara con la información del descriptor de segmento. Siempre que una de estas comprobaciones falla, se genera la excepción (interrupción) 13 (hex 0D). Esta excepción se denomina Falla de protección general (GPF).

Eso 13coincide 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 hacerlo, y realmente no importa cómo se implemente en el hardware.

trojanfoe
fuente
1
Sin embargo, los sistemas operativos modernos no utilizan segmentos para la protección de la memoria en general. Todo se hace con la MMU y daría lugar a un PF, vector 14 (normalmente se muestra como "Fallo de segmentación").
Mats Petersson
16

Me preguntaba por qué aparecía esto durante mis pruebas unitarias.

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

Resulta que una limpieza de ⌘K funcionó. Siempre me quedo boquiabierto cuando eso resuelve problemas reales.

ctietze
fuente
Esto también me solucionó en Swift. ¡Gracias!
lwdthe1
8

Tuve una excepción similar en Swift 4.2. Pasé alrededor de media hora tratando de encontrar un error en mi código, pero el problema desapareció después de cerrar Xcode y eliminar la carpeta de datos derivados. Aquí está el atajo:

rm -rf ~/Library/Developer/Xcode/DerivedData
Stanislau Baranouski
fuente
2

En mi caso, el error se produjo en Xcode al ejecutar una aplicación en el simulador de iOS. Si bien no puedo responder la pregunta específica "qué significa el error", puedo decir qué me ayudó, tal vez también ayude a otros.

La solución para mí fue Erase All Content and Settingsen el simulador y Clean Build Folder...en Xcode.

Manuel
fuente
1

Tuve este problema al salir de una vista (volver a la vista anterior).

la razón fue tener

addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    view.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
    view.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
    view.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
    view.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
])

Cambie safeAreaLayoutGuidepara selfsolucionar el problema.

El significado alinea la vista con la vista inicial, final, superior e inferior de la supervista en lugar de con el área segura)

Nuynait
fuente
0

Esto me sucedió porque no parecía gustarle a Xcode que usara el mismo nombre de variable en dos clases diferentes (que se ajustan al mismo protocolo, si eso importa, aunque el nombre de la variable no tiene nada relacionado en ningún protocolo). Simplemente renombré mi nueva variable.

Tuve que entrar en los setters donde se estrellaba para poder verlo mientras depuraba. Esta respuesta se aplica a iOS

Stephen J
fuente
0

Si el error se arroja dentro de un cierre que define selfcomo unowned, es posible que tenga limitaciones en lo que puede acceder y obtendrá este código de error en determinadas situaciones. Especialmente durante la depuración. Si este es su caso, intente cambiar [unowned self]a[weak self]

Matjan
fuente
0

Recibí este error al hacer esto:

 NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] initWithObjectsAndKeys:<#(nonnull id), ...#>, nil]; //with 17 objects and keys

Se fue cuando volví a:

NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] init];
[aDictionary setObject:object1 forKey:@"Key1"]; //17 times
Peter B. Kramer
fuente
0

Para mí, el problema relacionado con el guión gráfico existe la opción de compilación de ViewController para el conjunto iOS 9.0 y posterior configurado previamente para iOS 10.0 y posterior. En realidad, quiero degradar la versión de 10 a iOS 9.3.

Anil Kumar
fuente