Linguagem C - C/C++ Falha de segmentação

Junho 2017


O que significa uma falha de segmentação


Você está desenvolvendo uma aplicação no Linux em C/C++. Tudo corre bem, ele está compilando, "os pássaros estão cantando".
Então, você executa a aplicação para testá-la.
Aí você recebe uma destas duas mensagens:
 Falha de segmentação

ou
Segmentation fault


Se por um lado, quando ocorre um erro com um programa escrito em uma linguagem de alto nível (perl, python, java, etc ...), a mensagem de desbloqueio é mais detalhada: que tipo de exceção ocorreu? A que linha do programa a falha corresponde, etc ...

Por outro, em uma linguagem compilada (ou seja, transformada em linguagem facilmente compreensível por seu processador), como C ou C++, seu programa não está sob o controle de nenhum intérprete ou máquina virtual. Assimsendo, ninguém pod monitorar e analisar seus erros.

Felizmente, existem programas chamados desbloqueadores facilitar sua vida.

Saiba que um sistema operacional moderno (Windows NT/2000/XP/; Linux) aloca uma parte da memória para cada aplicação. Se um aplicativo tenta entrar diretamente em uma área de memória que não lhe pertence ou em uma área de memória incorreta, o sistema operacional vai interromper o aplicativo em curso e gerar um erro (Linux: Falha de segmentação).

Em C


Consideremos, por exemplo, um programa em C bem simples, que trava voluntariamente e gera uma falha de segmentação:

void execute_falha_segmentação() 
{ 
int *ponteiro_perigoso=(int *) 100; 
int test=* ponteiro_ perigoso; 
} 

int main(int argc, char ** argv) 
{ 
execute_falha_segmentação (); 
return 0; 
}


Na função execute_falha_segmentação, o ponteiro_perigoso aponta para o endereço 100 na memória.
Este é um endereço que não pode pertencer a uma aplicação normal.

Quando o ponteiro_perigoso tentará ler o que está no endereço de memória 100, para destacar o valor situado neste endereço na variável teste, o programa vai falhar.

E você receberá a mensagem "Falha de segmentação".

Para desbloquear este programa, vamos começar por compilá-lo carregando seus símbolos de desbloqueio. Isto permite, principalmente, carregar os nomes de funções e variáveis utilizadas no programa, depois de compilado; assim, o desbloqueador podeá rastrear o erro indicando os nomes das funções em causa, ao invés de dar apenas seu endereço.
Estou falando da opção-g

Vamos compilar:
gcc -g test.c -o test

E vamos executar o programa no desbloqueador:
gdb ./test

Você verá um prompt de comando que começa por:
(gdb)

Digite o comando run

Vejamos o que acontece:
(gdb) run 
Starting program: ~/test 

Program received signal SIGSEGV, Segmentation fault. 
0x08048334 in executa_falha_segmentação () at test.c:4 
4 int test=*ponteiro_perigoso;


O que pedir a mais: o desbloqueador mostra a linha em seu arquivo de origem que está
causando o erro, assim como a função em questão e o conteúdo da linha:

É um erro na função executa_falha_segmentação no arquivo fonte test.c na linha 4 cujo conteúdo é

int test=*ponteiro_perigoso;

Suponhemos agora que você queira saber que função chamou que outra função desde o início do programa até a ocorrência do erro.

Digite o comando bt:
(gdb) bt 
#0 0x08048334 in executa_falha_segmentação() at test.c:4 
#1 0x0804834e in main () at test.c:9

E você obtém outra vez o que você precisa!

Em C++


Para continuar com esse mesmo problema: as falhas de segmentação, não há muito a acrescentar para o C++, exceto que se trata de usar o comando g++ com a opção -g da mesma maneira que com o gcc.

O relatório do gdb será o mesmo, mas com os detalhes das classes em questão.

Exemplo:
//Arquivo teste.cpp 
class Test{ 
public: 
int a; 
Test(){}; 
~Test(){}; 
int incremente_a(){ a++; }; 
}; 

int main() 
{ 
Test *t; 
t=(Test *)100; 
t->incremente_a(); 
return 0; 
}


Compilamos assim:
g++ -g test.cpp -o test


Executamos o desbloqueador:
gdb ./test

Depois digite os mesmos comandos que antes e todos os detalhes aparecerão:
(gdb) run 
Starting program: ~/test 

Program received signal SIGSEGV, Segmentation fault. 
0x080483fc in Test::incremente_a (this=0x64) at test.cpp:7 
7 int incremente_a(){ a++; }; 
(gdb) bt 
#0 0x080483fc in Test::incremente_a (this=0x64) at test.cpp:7 
#1 0x080483e7 in main () at test.cpp:14 


Pronto.

Links




Tradução feita por Lucia Maurity y Nouira


Veja também

Artigo original publicado por . Tradução feita por pintuda. Última modificação: 4 de novembro de 2011 às 11:29 por pintuda.
Este documento, intitulado 'Linguagem C - C/C++ Falha de segmentação ', está disponível sob a licença Creative Commons. Você pode copiar e/ou modificar o conteúdo desta página com base nas condições estipuladas pela licença. Não se esqueça de creditar o CCM (br.ccm.net) ao utilizar este artigo.