Qual è il significato del codice di eccezione "EXC_I386_GPFLT"?


117

Qual è il significato del codice di eccezione EXC_I386_GPFLT?

Il suo significato varia a seconda della situazione?

In tal caso, mi riferisco al tipo EXC_BAD_ACCESSdi eccezione con codice di eccezioneEXC_I386_GPFLT

Il programma è sviluppato in Xcode 5.0.1, che si occupa cblas_zgemm()della libreria BLAS (beh, immagino non abbia importanza ...)

Grazie mille!

Risposte:


112

EXC_I386_GPFLT si riferisce sicuramente a "errore di protezione generale", che è il modo in cui x86 ti dice che "hai fatto qualcosa che non ti è permesso fare". In genere NON significa che si accede ai limiti di memoria, ma potrebbe essere che il codice stia uscendo dai limiti e causi l'utilizzo di codice / dati errato in un modo che costituisce una violazione della protezione di qualche tipo.

Sfortunatamente può essere difficile capire esattamente quale sia il problema senza più contesto, ci sono 27 diverse cause elencate nel mio Manuale del programmatore AMD64, Vol 2 del 2005 - a detta di tutti, è probabile che 8 anni dopo ne avrei aggiunti alcuni Di Più.

Se è un sistema a 64 bit, uno scenario plausibile è che il tuo codice utilizzi un "puntatore non canonico", il che significa che un indirizzo a 64 bit è formato in modo tale che i 16 bit superiori dell'indirizzo non lo siano tutte le copie dei primi 48 bit inferiori (in altre parole, i primi 16 bit di un indirizzo dovrebbero essere tutti 0 o tutti 1, in base al bit appena sotto i 16 bit). Questa regola è in atto per garantire che l'architettura possa "espandere in modo sicuro il numero di bit validi nell'intervallo di indirizzi". Ciò indicherebbe che il codice sta sovrascrivendo alcuni dati del puntatore con altre cose o sta uscendo dai limiti durante la lettura di un valore del puntatore.

Un'altra probabile causa è l'accesso non allineato con un registro SSE, in altre parole, la lettura di un registro SSE a 16 byte da un indirizzo che non è allineato a 16 byte.

Ci sono, come ho detto, molte altre possibili ragioni, ma la maggior parte di queste riguarda cose che il codice "normale" non farebbe in un sistema operativo a 32 o 64 bit (come il caricamento di registri di segmento con un indice del selettore non valido o la scrittura su MSR (registri specifici del modello)).


24

Per eseguire il debug e trovare la fonte: Abilita Zombies per l'app (Prodotto \ Schema) e Avvia strumenti, Seleziona Zombi. Esegui la tua app in Xcode Quindi vai su Strumenti per avviare la registrazione. Torna alla tua app e prova a generare l'errore. Gli strumenti dovrebbero rilevare una cattiva chiamata (a zombie) se ce n'è una.

Spero che sia d'aiuto!



23

Spesso puoi ottenere informazioni dai file di intestazione. Per esempio:

$ 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, quindi è un errore di protezione generale (come suggerisce comunque il nome). Cercare su Google "i386 errore di protezione generale" produce molti risultati, ma questo sembra interessante:

La protezione della memoria viene implementata anche utilizzando i descrittori di segmento. Innanzitutto, il processore verifica se un valore caricato in un registro di segmento fa riferimento a un descrittore valido. Quindi verifica che ogni indirizzo lineare calcolato si trovi effettivamente all'interno del segmento. Inoltre, il tipo di accesso (lettura, scrittura o esecuzione) viene confrontato con le informazioni nel descrittore di segmento. Ogni volta che uno di questi controlli fallisce, viene sollevata l'eccezione (interrupt) 13 (hex 0D). Questa eccezione è chiamata errore di protezione generale (GPF).

Che 13corrisponde a ciò che abbiamo visto nei file di intestazione, quindi sembra che la stessa cosa. Tuttavia, dal punto di vista del programmatore dell'applicazione, significa semplicemente che stiamo facendo riferimento alla memoria che non dovremmo essere, e non importa come sia implementata sull'hardware.


1
Tuttavia, i sistemi operativi moderni non utilizzano segmenti per la protezione della memoria in generale. È tutto fatto con la MMU e porterebbe a un PF, vettore 14 (di solito visualizzato come "errore di segmentazione").
Mats Petersson

16

Mi sono chiesto perché questo è apparso durante i miei test unitari.

Ho aggiunto una dichiarazione di metodo a un protocollo che includeva throws; ma il metodo di lancio potenziale non è stato nemmeno utilizzato in quel particolare test. Abilitare gli zombi nel test sembrava un problema.

Si scopre che un ⌘K clean ha funzionato. Sono sempre sbalordito quando questo risolve i problemi reali.


Questo ha risolto il problema anche per me in Swift. Grazie!
lwdthe1

8

Ho avuto un'eccezione simile in Swift 4.2. Ho passato circa mezz'ora a cercare un bug nel mio codice, ma il problema è scomparso dopo aver chiuso Xcode e rimosso la cartella dei dati derivati. Ecco la scorciatoia:

rm -rf ~/Library/Developer/Xcode/DerivedData

2

Nel mio caso l'errore è stato generato in Xcode durante l'esecuzione di un'app sul simulatore iOS. Anche se non posso rispondere alla domanda specifica "cosa significa l'errore", posso dire cosa mi ha aiutato, forse aiuta anche gli altri.

La soluzione per me era Erase All Content and Settingsnel simulatore e Clean Build Folder...in Xcode.


1

Ho riscontrato questo problema quando ho lasciato una vista (tornare alla vista precedente).

il motivo era avere

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

Modifica safeAreaLayoutGuideper selfrisolvere il problema.

Il significato allinea la vista con l'area iniziale, finale, superiore, inferiore della superview invece che con l'area sicura)


0

Questo è successo a me perché Xcode non sembrava apprezzare l'uso dello stesso nome di variabile in due classi diverse (che sono conformi allo stesso protocollo, se è importante, sebbene il nome della variabile non abbia nulla in relazione con alcun protocollo). Ho semplicemente rinominato la mia nuova variabile.

Ho dovuto entrare nei setter dove si stava bloccando per vederlo, durante il debug. Questa risposta si applica a iOS


0

Se l'errore viene generato all'interno di una chiusura che definisce selfcome unowned, potresti essere limitato a ciò a cui puoi accedere e otterrai questo codice di errore in determinate situazioni. Soprattutto durante il debug. Se questo è il tuo caso, prova a passare [unowned self]a[weak self]


0

Ho ricevuto questo errore mentre facevo questo:

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

È andato via quando sono tornato a:

NSMutableDictionary *aDictionary=[[NSMutableDictionary alloc] init];
[aDictionary setObject:object1 forKey:@"Key1"]; //17 times

0

Per me il problema relativo allo storyboard è disponibile l'opzione di build ViewController per il set iOS 9.0 e versioni successive precedentemente impostate per iOS 10.0 e versioni successive. In realtà voglio eseguire il downgrade della versione 10 a iOS 9.3.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.