GDB - Guia Rápido
Um depurador é um programa que executa outros programas, permitindo ao usuário exercer controle sobre esses programas e examinar variáveis quando surgem problemas.
GNU Debugger, que também é chamado gdb, é o depurador mais popular para sistemas UNIX para depurar programas C e C ++.
GNU Debugger ajuda você a obter informações sobre o seguinte:
Se um despejo de núcleo aconteceu, então em qual declaração ou expressão o programa travou?
Se ocorrer um erro durante a execução de uma função, qual linha do programa contém a chamada para essa função e quais são os parâmetros?
Quais são os valores das variáveis do programa em um determinado ponto durante a execução do programa?
Qual é o resultado de uma determinada expressão em um programa?
Como o GDB depura?
GDB permite que você execute o programa até um certo ponto, então pare e imprima os valores de certas variáveis naquele ponto, ou avance pelo programa uma linha por vez e imprima os valores de cada variável depois de executar cada linha.
GDB usa uma interface de linha de comando simples.
Pontos a serem observados
Embora o GDB possa ajudá-lo a descobrir bugs relacionados ao vazamento de memória, ele não é uma ferramenta para detectar vazamentos de memória.
O GDB não pode ser usado para programas que compilam com erros e não ajuda a corrigir esses erros.
Antes de iniciar a instalação, verifique se você já tem o gdb instalado em seu sistema Unix, emitindo o seguinte comando:
$gdb -help
Se o GDB estiver instalado, ele exibirá todas as opções disponíveis em seu GDB. Se o GDB não estiver instalado, prossiga para uma nova instalação.
Você pode instalar o GDB em seu sistema seguindo as etapas simples discutidas abaixo.
step 1: Verifique se você tem os pré-requisitos para instalar o gdb:
Um compilador C compatível com ANSI (gcc é recomendado - observe que gdb pode depurar códigos gerados por outros compiladores)
115 MB de espaço livre em disco são necessários na partição na qual você vai construir o gdb.
20 MB de espaço livre em disco são necessários na partição em que você vai instalar o gdb.
Programa de descompressão GNU, gzip
o make utilitário - a versão GNU é conhecida por funcionar sem problemas, outras provavelmente também funcionam.
step 2: Baixe a distribuição de origem do gdb em ftp.gnu.org/gnu/gdb. (Nós costumavamos gdb-6.6.tar.gz para essas instruções.) Coloque os arquivos de distribuição no diretório de construção.
step 3:No diretório de construção, descompacte gdb-6.6.tar.gz e extraia os arquivos de origem do arquivo. Assim que os arquivos forem extraídos, mude seu diretório de trabalho para o diretório gdb-6.6 que foi criado automaticamente no diretório de construção.
$ build> gzip -d gdb-6.6.tar.gz
$ build> tar xfv gdb-6.6.tar
$ build> cd gdb-6.6
step 4: Execute o script de configuração para configurar a árvore de origem para sua plataforma.
$ gdb-6.6> .⁄configure
step 5: Construa o gdb usando o make Utilitário.
$ gdb-6.6> make
step 6: Faça login como root e instale o gdb usando o seguinte comando.
$ gdb-6.6> make install
step 7: Se necessário, o espaço em disco pode ser recuperado excluindo o diretório de construção gdb e o arquivo compactado após a conclusão da instalação.
$ gdb-6.6> cd ..
$ build> rm -r gdb-6.6
$ build> rm gdb-6.6.tar
Agora você tem gdb instalado em seu sistema e está pronto para ser usado.
UMA Debugging Symbol Tablemapeia instruções no programa binário compilado para sua variável, função ou linha correspondente no código-fonte. Esse mapeamento pode ser algo como:
Instrução de programa ⇒ nome do item, tipo de item, arquivo original, número de linha definido.
As tabelas de símbolos podem ser incorporadas ao programa ou armazenadas como um arquivo separado. Portanto, se você planeja depurar seu programa, é necessário criar uma tabela de símbolos que terá as informações necessárias para depurar o programa.
Podemos inferir os seguintes fatos sobre tabelas de símbolos:
Uma tabela de símbolos funciona para uma versão específica do programa - se o programa mudar, uma nova tabela deve ser criada.
As compilações de depuração são geralmente maiores e mais lentas do que as compilações de varejo (não depuradas); as compilações de depuração contêm a tabela de símbolos e outras informações auxiliares.
Se você deseja depurar um programa binário que não compilou, você deve obter as tabelas de símbolos do autor.
Para permitir que o GDB seja capaz de ler todas as informações linha por linha da tabela de símbolos, precisamos compilá-la de maneira um pouco diferente. Normalmente compilamos nossos programas como:
gcc hello.cc -o hello
Em vez de fazer isso, precisamos compilar com o sinalizador -g conforme mostrado abaixo:
gcc -g hello.cc -o hello
GDB oferece uma grande lista de comandos, no entanto, os comandos a seguir são os usados com mais frequência:
b main - Coloca um ponto de interrupção no início do programa
b - Coloca um ponto de interrupção na linha atual
b N - Coloca um ponto de interrupção na linha N
b +N - Coloca um ponto de interrupção N linhas abaixo da linha atual
b fn - Coloca um ponto de interrupção no início da função "fn"
d N - Exclui o ponto de interrupção número N
info break - listar pontos de interrupção
r - Executa o programa até um ponto de interrupção ou erro
c - Continua executando o programa até o próximo ponto de interrupção ou erro
f - Funciona até que a função atual seja concluída
s - Executa a próxima linha do programa
s N - Executa as próximas N linhas do programa
n - Gosta de s, mas não entra nas funções
u N - Corre até você obter N linhas na frente da linha atual
p var - Imprime o valor atual da variável "var"
bt - Imprime um rastreamento de pilha
u - Sobe um nível na pilha
d - Desce um nível na pilha
q - Sai do gdb
Primeiros passos: começando e parando
gcc -g meuprograma.c
Compila myprogram.c com a opção de depuração (-g). Você ainda obtém um a.out, mas ele contém informações de depuração que permitem usar variáveis e nomes de funções dentro do GDB, em vez de locais de memória bruta (não é divertido).
gdb a.out
Abre o GDB com o arquivo a.out, mas não executa o programa. Você verá um prompt (gdb) - todos os exemplos são desse prompt.
r
r arg1 arg2
r <arquivo1
Três maneiras de executar “a.out”, carregado anteriormente. Você pode executá-lo diretamente (r), passar argumentos (r arg1 arg2) ou inserir um arquivo. Normalmente, você definirá pontos de interrupção antes de executar.
help
h pontos de interrupção
Lista tópicos de ajuda (ajuda) ou obtém ajuda em um tópico específico (h pontos de interrupção). GDB está bem documentado.
q - Saia do GDB
Percorrendo o código
A revisão permite rastrear o caminho do seu programa e se concentrar no código que está travando ou retornando uma entrada inválida.
l
l 50
eu minha função
Lista 10 linhas de código-fonte para a linha atual (l), uma linha específica (l 50) ou para uma função (l myfunction).
Próximo
Executa o programa até a próxima linha e, em seguida, faz uma pausa. Se a linha atual for uma função, ela executa a função inteira e depois faz uma pausa.next é bom para percorrer seu código rapidamente.
degrau
Executa a próxima instrução, não a linha. Se a instrução atual está definindo uma variável, é o mesmo quenext. Se for uma função, ele pulará para a função, executará a primeira instrução e fará uma pausa.step é bom para mergulhar nos detalhes do seu código.
terminar
Conclui a execução da função atual e faz uma pausa (também chamada de saída). Útil se você acidentalmente entrou em uma função.
Pontos de interrupção ou pontos de controle
Os pontos de interrupção desempenham um papel importante na depuração. Eles pausam (interrompem) um programa quando ele atinge um determinado ponto. Você pode examinar e alterar variáveis e retomar a execução. Isso é útil quando ocorre alguma falha de entrada ou quando as entradas precisam ser testadas.
pausa 45
quebrar minha função
- Define um ponto de interrupção na linha 45 ou em minha função. O programa fará uma pausa quando atingir o ponto de interrupção.
assistir x == 3
Define um ponto de controle, que pausa o programa quando uma condição muda (quando x == 3 muda). Os pontos de controle são ótimos para certas entradas (myPtr! = NULL) sem ter que interromper a cada chamada de função.
continuar
Retoma a execução após ser pausado por um breakpoint / watchpoint. O programa continuará até atingir o próximo breakpoint / watchpoint.
deletar N
- Exclui o ponto de interrupção N (os pontos de interrupção são numerados quando criados).
Configurando Variáveis
Visualizar e alterar variáveis em tempo de execução é uma parte crítica da depuração. Tente fornecer entradas inválidas para funções ou executar outros casos de teste para encontrar a causa raiz dos problemas. Normalmente, você visualizará / definirá variáveis quando o programa for pausado.
imprimir x
Imprime o valor atual da variável x. Ser capaz de usar os nomes de variáveis originais é o motivo pelo qual o sinalizador (-g) é necessário; programas compilados regularmente têm essas informações removidas.
definir x = 3
definir x = y
- Define x para um valor definido (3) ou para outra variável (y)
chamar minha função ()
chamar mioterfunção (x)
chamar strlen (mystring)
Chama funções definidas pelo usuário ou do sistema. Isso é extremamente útil, mas cuidado ao chamar funções com erros.
exibir x
Exibe constantemente o valor da variável x, que é mostrado após cada passo ou pausa. Útil se você estiver verificando constantemente um determinado valor.
não mostrar x
- Remove a exibição constante de uma variável exibida pelo comando display.
Backtrace e mudança de frames
Uma pilha é uma lista das chamadas de função atuais - ela mostra onde você está no programa. Um quadro armazena os detalhes de uma única chamada de função, como os argumentos.
bt
Backtracesou imprime a pilha de funções atual para mostrar onde você está no programa atual. Se main chamar a função a (), que chama b (), que chama c (), o backtrace é
c <= current location
b
a
main
up
baixa
Passe para o próximo quadro para cima ou para baixo na pilha de funções. Se você está emc, você pode mover para b ou a para examinar as variáveis locais.
Retorna
- Retorna da função atual.
Manuseio de sinais
Os sinais são mensagens lançadas após certos eventos, como um cronômetro ou erro. GDB pode pausar quando encontra um sinal; você pode preferir ignorá-los.
lidar com [nome do sinal] [ação]
lidar com SIGUSR1 nostop
lidar com SIGUSR1 noprint
lidar com SIGUSR1 ignorar
Instrua o GDB para ignorar um certo sinal (SIGUSR1) quando ele ocorrer. Existem vários níveis de ignorar.
Percorra os exemplos a seguir para entender o procedimento de depuração de um programa e despejo de núcleo.
-
Este exemplo demonstra como você capturaria um erro que está acontecendo devido a uma exceção gerada durante a divisão por zero.
-
Este exemplo demonstra um programa que pode despejar um núcleo devido à memória não inicializada.
Ambos os programas são escritos em C ++ e geram dump de memória devido a diferentes razões. Depois de passar por esses dois exemplos, você deve estar em uma posição para depurar seus programas C ou C ++ que geram despejos de memória.
Depois de passar por este tutorial, você deve ter adquirido um bom entendimento de depuração de um programa C ou C ++ usando o GNU Debugger. Agora deve ser muito fácil para você aprender a funcionalidade de outros depuradores porque eles são muito semelhantes ao GDB. É altamente recomendável que você também examine outros depuradores para se familiarizar com seus recursos.
Existem alguns bons depuradores disponíveis no mercado:
DBX Debugger- Este depurador vem junto com o Sun Solaris e você pode obter informações completas sobre este depurador usando a página de manual do dbx, ou seja, man dbx .
DDD Debugger- Esta é uma versão gráfica do dbx e disponível gratuitamente no Linux. Para ter um detalhe completo, use a página man do ddd, ou seja, man ddd .
Você pode obter detalhes abrangentes sobre o GNU Debugger no seguinte link: Debugging with GDB