As falhas de segmentação podem ser difíceis de depurar porque geralmente resultam em travamentos sem fornecer mensagens de erro detalhadas. No entanto, ferramentas como o GDB (GNU Debugger) podem ajudar a identificar a origem da falha de segmentação examinando o estado do programa e o rastreamento de pilha no momento do erro.
É importante observar que as falhas de segmentação normalmente são causadas por erros de programação e são consideradas bugs. Eles devem ser corrigidos revisando e corrigindo o código problemático. As causas comuns de falhas de segmentação incluem:
- Desreferenciando os ponteiros nulos ou não inicializados
- Escrevendo ou lendo fora dos limites de um array
- Usando uma memória que foi previamente desalocada ou liberada
- Estouro de pilha ou corrupção de pilha
- Usando variáveis não inicializadas
Examinando cuidadosamente seu código e usando ferramentas de depuração como GDB, você pode identificar e corrigir as falhas de segmentação, garantindo que seu programa funcione corretamente e não encontre esses erros.
Depurador GDB
GDB (GNU Debugger) é uma ferramenta de depuração poderosa que ajuda a identificar e analisar problemas em programas compilados, incluindo falhas de segmentação. Ele permite examinar o estado do programa, acionar os pontos de interrupção e observar o fluxo de execução.
Para usar o GDB de forma eficaz para depurar as falhas de segmentação, você precisa compilar seu programa C++ com os símbolos de depuração habilitados. Esses símbolos incluem informações adicionais sobre a estrutura, variáveis e funções do programa que auxiliam no processo de depuração.
Encontrando a falha de segmentação em C++ com GDB
Aqui está um exemplo de trecho de código que causa uma falha de segmentação:
#includeinterno principal ( ) {
interno * PTR = nullptr ;
* PTR = 5 ;
retornar 0 ;
}
Vamos primeiro explicar o código. A seguir, discutiremos em etapas como encontrar uma falha de segmentação no código anterior.
A diretiva de pré-processador “#include
Dentro da função main(), há uma declaração de uma variável de ponteiro “ptr” do tipo int*. O valor “nullptr” é usado como inicialização do ponteiro que é um valor especial de ponteiro nulo que indica que ele não aponta para nenhum localização de memória válida.
As tentativas de desreferência são feitas com o ponteiro nulo “ptr” na linha seguinte que é “*ptr = 5;”. Neste caso, como “ptr” está definido como “nullptr”, não há local de memória válido para acessar.
Agora discutiremos alguns passos que precisam ser adotados para compilar o programa a fim de encontrar a falha de segmentação.
Etapa 1: habilite os símbolos de depuração
Para começar, certifique-se de compilar seu programa C++ com os símbolos de depuração habilitados. Para fornecer informações de depuração ao arquivo executável durante a compilação, use o sinalizador “-g”. Considere o caso em que temos um arquivo C++ chamado “main.cpp”.
$ g++ -g principal.cpp -o principalEtapa 2: execute o GDB
Depois que o programa for compilado com símbolos de depuração, execute o GDB passando o arquivo executável como argumento.
$ gdb principalEtapa 3: inicie o programa
Inicie o programa digitando “run” ou “r” no prompt do GDB:
$ ( gdb ) correrSeu programa começará então a ser executado.
Etapa 4: Identifique a falha de segmentação
O programa continua em execução até encontrar uma falha de segmentação. O programa então para de funcionar e o GDB produz uma mensagem de erro.
Por exemplo: vamos considerar o código explicado anteriormente onde quando tentamos atribuir o valor 5 ao local de memória apontado pelo ponteiro nulo, resulta em uma falha de segmentação. O programa termina imediatamente na linha onde ocorre a falha de segmentação.
Ao executar este programa com GDB, você verá uma saída semelhante à seguinte:
Esta saída indica que ocorreu uma falha de segmentação na função principal na linha 5 do arquivo “main.cpp”.
Etapa 5: examine o rastreamento de pilha
Para obter mais informações sobre a falha de segmentação, você pode examinar o rastreamento de pilha usando o comando “backtrace” ou simplesmente “bt”. Este comando exibe a sequência de chamadas de função que leva ao travamento.
$ ( gdb ) aliásO rastreamento de pilha é exibido, indicando as funções que são chamadas antes da falha de segmentação:
Esta saída nos informa que a falha de segmentação ocorreu na função principal na linha 5 do arquivo “main.cpp”.
Etapa 6: definir os pontos de interrupção
Para investigar mais detalhadamente, você pode definir pontos de interrupção em linhas específicas de código para interromper a execução do programa nesses pontos. Isso permite inspecionar o estado e as variáveis do programa. Por exemplo, para definir um ponto de interrupção na linha 5 do “main.cpp”, use o comando “break” da seguinte forma:
$ ( gdb ) quebrar principal.cpp: 5Isso define um ponto de interrupção na linha 5 do arquivo “main.cpp”:
Etapa 7: retomar a execução
Após definir os breakpoints, retome a execução do programa usando o comando “continue” ou simplesmente “c”:
$ ( gdb ) continuarO programa continua em execução até atingir o ponto de interrupção.
Etapa 8: inspecionar as variáveis e o código
Depois que o programa for interrompido em um ponto de interrupção, você poderá usar vários comandos do GDB para examinar as variáveis, percorrer o código e investigar a causa da falha de segmentação.
Etapa 9: saia do GDB
Depois de terminar a depuração, você pode sair do GDB usando o comando “quit”:
$ ( gdb ) desistirIsso fornece uma visão geral básica do uso do GDB para encontrar falhas de segmentação nos programas C++. O GDB fornece muitos mais recursos e comandos que podem ajudar na depuração, e você pode consultar a documentação do GDB para obter informações mais detalhadas.
Conclusão
Este artigo demonstra a utilização do GDB para encontrar a falha de segmentação em C++. Explicamos a você os passos que precisam ser seguidos. Estas etapas fornecem uma explicação abrangente sobre como encontrar uma falha de segmentação em C++ usando GDB. Seguindo essas etapas e utilizando os recursos do GDB, você pode localizar e depurar com eficácia a origem da falha de segmentação em seu programa C++.