Depurando com gdb

O depurador GNU (gdb) permite examinar dentro de outro programa enquanto o programa é executado ou de modo retroativo para ver o que um programa estava fazendo no momento em que travou.

O gdb permite examinar e controlar a execução do código e é útil para avaliar as causas dos travamentos ou de comportamento geral incorreto. O gdb não manipula processos Java™ , portanto, é de uso limitado em um programa Java puro. É útil para depurar bibliotecas nativas e a própria JVM.

Executando o gdb

É possível executar o gdb de três maneiras:

Iniciando um programa
Geralmente o comando: gdb <application> é usado para iniciar um programa sob o controle do gdb. No entanto, devido à maneira como o Java é ativado, deve-se iniciar gdb configurando uma variável de ambiente e, em seguida, chamando Java:
export IBM_JVM_DEBUG_PROG=gdb
java
Em seguida, você recebe um prompt gdb e fornece o comando de execução e os argumentos Java:
r <java_arguments>
Conectando-se a um Programa em Execução
Se um programa Java já estiver em execução, será possível controlá-lo em gdb O ID do processo do programa em execução é necessário e, em seguida, gdb é iniciado com o aplicativo Java como o primeiro argumento e o ID do processo como o segundo argumento:
gdb <Java Executable> <PID>

Quando o gdb é conectado a um programa em execução, este programa é parado e sua posição no código é exibida para o visualizador. O programa está, então, sob o controle do gdb e é possível começar a emitir comandos para configurar e visualizar as variáveis e, geralmente, controlar a execução do código.

Executando em um Dump do Sistema (Arquivo Principal)
Um dump do sistema é produzido geralmente quando um programa trava. O gdb pode ser executado neste dump do sistema. O dump do sistema contém o estado do programa quando o travamento ocorreu. Use o gdb para examinar os valores de todas as variáveis e registros que levam a um travamento. Estas informações ajudam a descobrir o que causou o travamento. Para depurar um dump do sistema, inicie gdb com o arquivo de aplicativos Java como o primeiro argumento e o nome do dump do sistema como o segundo argumento:
gdb <Java Executable> <system dump>

Quando você executa o gdb em um dump do sistema, ele inicialmente mostra informações tais como o sinal de finalização que o programa recebeu, a função que estava sendo executada no momento e até a linha de código que gerou a falha.

Quando um programa está sob o controle do gdb, uma mensagem de boas-vindas é exibida seguida por um prompt (gdb). O programa agora está esperando você inserir instruções. Para cada instrução, o programa continua da maneira que você escolher.

Configurando Pontos de Interrupção e Watchpoints

Os pontos de interrupção podem ser configurados para uma linha ou função específica usando o comando:

break linenumber

ou

break functionName

Após ter configurado um ponto de interrupção, use o comando continue para permitir que o programa execute até atingir um ponto de interrupção.

Configure pontos de interrupção usando condicionais para que o programa pare apenas quando a condição especificada for atingida. Por exemplo, usar breakpoint 39 if var == value faz com que o programa pare quando ele atingir a linha 39, mas apenas se a variável for igual ao valor especificado.

Se desejar saber onde e quando uma variável se torna um valor determinado, é possível usar um watchpoint. Configure o watchpoint quando a variável em questão estiver no escopo. Após fazer isso, você será alertado sempre que esta variável tiver o valor especificado. A sintaxe do comando é: watch var == value.

Para ver quais pontos de interrupção e watchpoints estão configurados, use o comando info:

info break
info watch
Quando o gdb atingir um ponto de interrupção ou um watchpoint, ele imprimirá a linha de código que ele está configurado para executar em seguida. A configuração de um ponto de interrupção na linha 8 fará com que o programa pare após concluir a execução da linha 7, mas antes da execução da linha 8. Além de pontos de interrupção e watchpoints, o programa também para quando recebe certos sinais do sistema. Usando os comandos a seguir, é possível parar a ferramenta de depuração parando toda vez que ela receber estes sinais do sistema:
handle sig32 pass nostop noprint 
handle sigusr2 pass nostop noprint 

Examinando o Código

Quando a posição correta do código tiver sido atingida, haverá várias maneiras de examinar o código. A mais útil é backtrace (abreviada para bt), que mostra a pilha de chamada. A pilha de chamada é a coleta de quadros de função, em que cada quadro de função contém informações tais como parâmetros da função e variáveis locais. Estes quadros de função são colocados na pilha de chamada na ordem em que são executados. Isto significa que a função chamada mais recentemente é exibida na parte superior da pilha de chamada. É possível seguir a trilha de execução de um programa examinando a pilha de chamada. Quando a pilha de chamada é exibida, ela mostra um número de quadro no início da linha, seguido pelo endereço da função de chamada, seguido pelo nome da função e pelo arquivo de origem da função. Por exemplo:
#6 0x804c4d8 in myFunction () at myApplication.c

Para visualizar informações mais detalhadas sobre um quadro de função, use o comando frame juntamente com um parâmetro que especifica o número do quadro. Depois de ter selecionado um quadro, é possível exibir suas variáveis usando o comando print var

Use o comando print para alterar o valor de uma variável; por exemplo, print var = newValue.

O comando info locals exibe os valores de todas as variáveis locais na função selecionada.

Para seguir a sequência exata de execução de seu programa, use os comandos step e next. Ambos os comandos executam um parâmetro opcional especificando o número de linhas a executar. Entretanto, next trata as chamadas de função como uma única linha de execução, enquanto step progride através de cada linha da função chamada, uma etapa por vez.

Comandos Úteis

Quando tiver concluído a depuração de seu código, o comando run faz com que o programa seja executado até o final ou até seu ponto de travamento. O comando quit é usado para sair do gdb.

Outros comandos úteis são:

ptype
Imprime o tipo de dado da variável.
info share
Imprime os nomes das bibliotecas compartilhadas que são carregadas atualmente.
info functions
Imprime todos os protótipos de função.
list
Mostra as 10 linhas de código de origem ao redor da linha atual.
help
Exibe uma lista de assuntos, cada um dos quais pode ter o comando de ajuda chamado nele, para exibir a ajuda detalhada nesse tópico.