Quelle est la signification du code d'exception «EXC_I386_GPFLT»?

117

Quelle est la signification du code d'exception EXC_I386_GPFLT?

Sa signification varie-t-elle selon la situation?

Dans ce cas, je fais référence au type EXC_BAD_ACCESSd'exception avec code d'exceptionEXC_I386_GPFLT

Le programme est développé en Xcode 5.0.1, traitant cblas_zgemm()de la bibliothèque BLAS (enfin, je suppose que cela n'a pas d'importance ...)

Merci beaucoup!

Lewen
la source

Réponses:

112

EXC_I386_GPFLT fait sûrement référence à "Erreur de protection générale", qui est le moyen pour x86 de vous dire que "vous avez fait quelque chose que vous n'êtes pas autorisé à faire". Cela NE signifie généralement PAS que vous accédez en dehors des limites de la mémoire, mais il se peut que votre code soit hors limites et que le mauvais code / données soit utilisé d'une manière qui entraîne une violation de la protection.

Malheureusement, il peut être difficile de comprendre exactement quel est le problème sans plus de contexte, il y a 27 causes différentes répertoriées dans mon manuel du programmeur AMD64, Vol 2 de 2005 - selon tous les témoignages, il est probable que 8 ans plus tard en auraient ajouté quelques-unes. plus.

S'il s'agit d'un système 64 bits, un scénario plausible est que votre code utilise un "pointeur non canonique" - ce qui signifie qu'une adresse 64 bits est formée de telle manière que les 16 bits supérieurs de l'adresse ne sont pas toutes les copies du haut des 48 bits inférieurs (en d'autres termes, les 16 premiers bits d'une adresse doivent tous être 0 ou tous 1, sur la base du bit juste en dessous de 16 bits). Cette règle est en place pour garantir que l'architecture peut "augmenter en toute sécurité le nombre de bits valides dans la plage d'adresses". Cela indiquerait que le code écrase certaines données de pointeur par d'autres éléments, ou sort des limites lors de la lecture d'une valeur de pointeur.

Une autre cause probable est l'accès non aligné avec un registre SSE - en d'autres termes, la lecture d'un registre SSE de 16 octets à partir d'une adresse qui n'est pas alignée sur 16 octets.

Il y a, comme je l'ai dit, de nombreuses autres raisons possibles, mais la plupart impliquent des choses que le code «normal» ne ferait pas dans un système d'exploitation 32 ou 64 bits (comme le chargement de registres de segment avec un index de sélecteur invalide ou l'écriture dans MSR (registres spécifiques au modèle)).

Mats Petersson
la source
24

Pour déboguer et trouver la source: Activez Zombies pour l'application (Produit \ Scheme) et Launch Instruments, sélectionnez Zombies. Exécutez votre application dans Xcode, puis accédez à Instruments pour démarrer l'enregistrement. Revenez à votre application et essayez de générer l'erreur. Les instruments doivent détecter un mauvais appel (au zombie) s'il y en a un.

J'espère que ça aide!

Khalid Mammadov
la source
23

Vous pouvez souvent obtenir des informations à partir des fichiers d'en-tête. Par exemple:

$ 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, donc c'est un défaut de protection général (comme son nom l'indique quand même). Googler "i386 general protection fault" donne de nombreux résultats, mais cela semble intéressant:

La protection de la mémoire est également mise en œuvre à l'aide des descripteurs de segment. Tout d'abord, le processeur vérifie si une valeur chargée dans un registre de segment fait référence à un descripteur valide. Ensuite, il vérifie que chaque adresse linéaire calculée se trouve réellement dans le segment. En outre, le type d'accès (lecture, écriture ou exécution) est vérifié par rapport aux informations du descripteur de segment. Chaque fois qu'une de ces vérifications échoue, l'exception (interruption) 13 (hex 0D) est déclenchée. Cette exception est appelée une erreur de protection générale (GPF).

Cela 13correspond à ce que nous avons vu dans les fichiers d'en-tête, donc cela ressemble à la même chose. Cependant, du point de vue du programmeur d'application, cela signifie simplement que nous référençons la mémoire que nous ne devrions pas être, et peu importe comment elle est implémentée sur le matériel.

cheval de Troie
la source
1
Cependant, les systèmes d'exploitation modernes n'utilisent pas de segments pour la protection de la mémoire en général. Tout cela est fait avec la MMU, et conduirait à un PF, vecteur 14 (généralement affiché comme "Défaut de segmentation").
Mats Petersson
16

Je me suis demandé pourquoi cela est apparu lors de mes tests unitaires.

J'ai ajouté une déclaration de méthode à un protocole qui comprenait throws; mais la méthode de projection potentielle n'a même pas été utilisée dans ce test particulier. Activer Zombies dans le test semblait trop compliqué.

Il s'avère qu'un nettoyage de ⌘K a fait l'affaire. Je suis toujours sidéré quand cela résout des problèmes réels.

ctietze
la source
Cela a aussi résolu le problème pour moi dans Swift. Merci!
lwdthe1
8

J'ai eu une exception similaire à Swift 4.2. J'ai passé environ une demi-heure à essayer de trouver un bogue dans mon code, mais le problème a disparu après la fermeture de Xcode et la suppression du dossier de données dérivé. Voici le raccourci:

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

Dans mon cas, l'erreur a été générée dans Xcode lors de l'exécution d'une application sur le simulateur iOS. Bien que je ne puisse pas répondre à la question spécifique «ce que signifie l'erreur», je peux dire ce qui m'a aidé, peut-être que cela aide aussi les autres.

La solution pour moi était Erase All Content and Settingsdans le simulateur et Clean Build Folder...dans Xcode.

Manuel
la source
1

J'ai eu ce problème en quittant une vue (revenez à la vue précédente).

la raison était d'avoir

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)
])

Changez safeAreaLayoutGuidepour selfrésoudre le problème.

La signification aligne la vue avec le début, la fin, le haut, le bas du superview au lieu de la zone de sécurité)

nuynait
la source
0

Cela m'est arrivé parce que Xcode ne semblait pas m'aimer en utilisant le même nom de variable dans deux classes différentes (qui se conforment au même protocole, si cela compte, bien que le nom de la variable n'ait rien de lié dans aucun protocole). J'ai simplement renommé ma nouvelle variable.

J'ai dû entrer dans les setters où il plantait pour le voir, pendant le débogage. Cette réponse s'applique à iOS

Stephen J
la source
0

Si l'erreur est lancée à l'intérieur d'une fermeture qui définit selfcomme unowned, vous pouvez être limité dans ce que vous pouvez accéder et obtiendrez ce code d'erreur dans certaines situations. Surtout lors du débogage. Si tel est le cas pour vous, essayez de passer [unowned self]à[weak self]

Matjan
la source
0

J'ai eu cette erreur en faisant ceci:

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

Cela a disparu quand je suis revenu à:

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

Pour moi, il s'agit d'un problème lié au storyboard, il existe une option de build ViewController pour l'ensemble iOS 9.0 et versions ultérieures précédemment définies pour iOS 10.0 et versions ultérieures. En fait, je veux rétrograder le ver de 10 à iOS 9.3.

Anil kumar
la source