Qual é o significado do código de exceção “EXC_I386_GPFLT”?

117

Qual é o significado do código de exceção EXC_I386_GPFLT?

Seu significado varia de acordo com a situação?

Nesse caso, estou me referindo ao tipo de EXC_BAD_ACCESSexceção com código de exceçãoEXC_I386_GPFLT

O programa é desenvolvido em Xcode 5.0.1, tratando cblas_zgemm()da biblioteca BLAS. (Bem, acho que não importa ...)

Muito obrigado!

Lewen
fonte

Respostas:

112

EXC_I386_GPFLT certamente se refere a "Falha de proteção geral", que é a maneira do x86 dizer que "você fez algo que não tem permissão para fazer". Normalmente NÃO significa que você acessou fora dos limites de memória, mas pode ser que seu código esteja saindo dos limites e fazendo com que códigos / dados inválidos sejam usados ​​de uma maneira que crie uma violação de proteção de algum tipo.

Infelizmente, pode ser difícil descobrir exatamente qual é o problema sem mais contexto. Existem 27 causas diferentes listadas no meu Manual do Programador AMD64, Vol 2 de 2005 - por todas as contas, é provável que 8 anos depois teria adicionado alguns Mais.

Se for um sistema de 64 bits, um cenário plausível é que seu código esteja usando um "ponteiro não canônico" - o que significa que um endereço de 64 bits é formado de forma que os 16 bits superiores do endereço não sejam todas as cópias do topo dos 48 bits inferiores (em outras palavras, os 16 bits principais de um endereço devem ser todos 0 ou 1, com base no bit logo abaixo de 16 bits). Essa regra existe para garantir que a arquitetura possa "expandir com segurança o número de bits válidos no intervalo de endereços". Isso indicaria que o código está sobrescrevendo alguns dados de ponteiro por outras coisas ou saindo dos limites ao ler algum valor de ponteiro.

Outra causa provável é o acesso desalinhado com um registro SSE - em outras palavras, a leitura de um registro SSE de 16 bytes de um endereço que não está alinhado com 16 bytes.

Existem, como eu disse, muitos outros motivos possíveis, mas a maioria deles envolve coisas que o código "normal" não faria em um sistema operacional de 32 ou 64 bits (como carregar registradores de segmento com índice de seletor inválido ou gravar em MSR (registros específicos do modelo)).

Mats Petersson
fonte
24

Para depurar e encontrar a fonte: Habilite Zumbis para o aplicativo (Produto \ Esquema) e Lance Instrumentos, selecione Zumbis. Execute seu aplicativo no Xcode Em seguida, vá para Instrumentos iniciar gravação. Volte para seu aplicativo e tente gerar o erro. Os instrumentos devem detectar uma chamada incorreta (para o zumbi), se houver.

Espero que ajude!

Khalid Mammadov
fonte
23

Freqüentemente, você pode obter informações dos arquivos de cabeçalho. Por exemplo:

$ 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, então é uma falha de proteção geral (como o próprio nome sugere). Pesquisar "falha de proteção geral i386" no Google produz muitos acertos, mas este parece interessante:

A proteção de memória também é implementada usando os descritores de segmento. Primeiro, o processador verifica se um valor carregado em um registro de segmento faz referência a um descritor válido. Em seguida, ele verifica se cada endereço linear calculado está realmente dentro do segmento. Além disso, o tipo de acesso (leitura, gravação ou execução) é verificado em relação às informações no descritor de segmento. Sempre que uma dessas verificações falha, a exceção (interrupção) 13 (hex 0D) é gerada. Essa exceção é chamada de Falha de proteção geral (GPF).

Isso 13corresponde ao que vimos nos arquivos de cabeçalho, por isso parece a mesma coisa. No entanto, do ponto de vista do programador do aplicativo, significa apenas que estamos fazendo referência a uma memória que não deveríamos estar, e realmente não importa como ela é implementada no hardware.

trojanfoe
fonte
1
Os sistemas operacionais modernos não usam segmentos para proteção de memória em geral, entretanto. Tudo é feito com a MMU e levaria a um PF, vetor 14 (geralmente exibido como "Falha de segmentação").
Mats Petersson,
16

Eu me perguntei por que isso apareceu durante meus testes de unidade.

Eu adicionei uma declaração de método a um protocolo que incluía throws; mas o método de arremesso potencial nem mesmo foi usado naquele teste específico. Habilitar Zumbis no teste parecia muito problemático.

Acontece que um ⌘K limpo funcionou. Sempre fico pasmo quando isso resolve problemas reais.

ctietze
fonte
Isso também corrigiu para mim no Swift. Obrigado!
lwdthe1 de
8

Tive uma exceção semelhante no Swift 4.2. Passei cerca de meia hora tentando encontrar um bug no meu código, mas o problema foi resolvido depois de fechar o Xcode e remover a pasta de dados derivados. Aqui está o atalho:

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

No meu caso, o erro foi lançado no Xcode ao executar um aplicativo no simulador iOS. Embora não possa responder à pergunta específica "o que significa o erro", posso dizer o que me ajudou, talvez também ajude os outros.

A solução para mim foi Erase All Content and Settingsno simulador e Clean Build Folder...no Xcode.

Manuel
fonte
1

Tive esse problema ao sair de uma visualização (voltar para a visualização anterior).

a razão foi ter

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

Mude safeAreaLayoutGuidepara selfresolver o problema.

O significado alinha a visualização com a visão frontal, posterior, superior, inferior, em vez da área segura)

Nuynait
fonte
0

Isso aconteceu comigo porque o Xcode não pareceu gostar de mim usando o mesmo nome de variável em duas classes diferentes (que estão em conformidade com o mesmo protocolo, se isso importa, embora o nome da variável não tenha nada relacionado em nenhum protocolo). Simplesmente renomeei minha nova variável.

Eu tive que entrar nos setters onde ele estava travando para poder vê-lo durante a depuração. Esta resposta se aplica ao iOS

Stephen J
fonte
0

Se o erro for lançado dentro de um fechamento que define selfcomo unowned, você pode estar limitado no que pode acessar e obterá esse código de erro em determinadas situações. Especialmente durante a depuração. Se este for o seu caso, tente mudar [unowned self]para[weak self]

Matjan
fonte
0

Recebi este erro ao fazer isso:

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

Ele foi embora quando eu voltei para:

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

Para mim, é um problema relacionado ao storyboard, há a opção de construção do ViewController para o conjunto iOS 9.0 e posterior, previamente definido para o iOS 10.0 e posterior. Na verdade, eu quero fazer o downgrade da versão 10 para iOS 9.3.

Anil Kumar
fonte