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:
Em seguida, você recebe um prompt gdb e fornece o comando de execução e os argumentos Java:export IBM_JVM_DEBUG_PROG=gdb 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
handle sig32 pass nostop noprint
handle sigusr2 pass nostop noprint
Examinando o Código
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.