GDB - GNU Debugger



Um debugger ajuda o programador no processo de depuração de erros de um programa.

Uma forma habitual de depurar erros num programa é, imprimir o valor de certas variáveis e/ou certos comentários, de forma a localizar e perceber o problema. Outra forma é usar um debugger. Neste último caso o debugger oferece-nos uma série de potencialidades tais como, parar a execução do programa num dado ponto, examinar o conteúdo das variáveis, alterar o conteúdo das variáveis,...

Na prática o programador experiente usa a combinação das duas técnicas anteriores.

Erros

Podemos dividir os erros dum programa em dois tipos: Os debuggers são usados para resolver erros do segundo tipo.

Executar o GDB

Compile o seu programa do seguinte modo:

            gcc -g -o prog prog.c

A opção -g destina-se a instruir o gcc a produzir informação de debugging para posterior utilização. De seguida faça:
 

            gdb
           (gdb) file prog

O gdb lê o executável do programa em causa.

Utilizadores de emacs: Fazer M-x gdb <ENTER> e introduzir o nome do executável no mini-buffer.

Nota: Em qualquer altura, pode utilizar o comando help para obter ajuda dentro do gdb.

Executar um programa

A execução de um programa dentro do gdb é feita com o seguinte comando:

           (gdb) run <argumentos_linha_comandos>

Onde <argumentos_linha_comandos> são os argumentos que o programa aceita normalmente na linha de comandos . Posteriormente veremos como parar a execução num dado ponto (breakpoint) e como executar uma instrução ou função de cada vez (controlo de execução).

Listar o programa

Em qualquer altura podemos listar o código fonte de um programa usando o comando list ou simplesmente l:

           (gdb) list

Lista as 10 linhas seguintes do programa.

           (gdb) list n

Lista as linhas de n-5 a n+4.

Utilizadores de emacs: A listagem do programa é feita pelo próprio emacs os caracteres "=>" assinalam a linha em execução.

Pontos de paragem: Breakpoints

O GDB dá-nos a possibilidade de pararmos a execução do programa em qualquer sítio de forma analisarmos a sua execução em pormenor.  O comando break ou simplesmente b, permite assinalar uma linha do programa onde a execução deve parar. Podemos indicar o nome da função onde o programa deve parar. Por exemplo:

           (gdb) break calcula

Breakpoint 1 at 0x8048499: file prog.c, line 15.

Indica que a execução deve parar no início da função calcula. Podemos também indicar a linha em que o programa deve parar:

           (gdb) break 18

Breakpoint 2 at 0x80484af: file prog.c, line 18

Para saber quais os breakpoints que temos neste momento:

           (gdb) info break

Para apagar um breakpoint:

           (gdb) delete n

Onde n é o número do breakpoint. Se n for omitido apaga todos os breakpoints. Existem ainda os comandos enable e disable que permitem activar/desactivar breakpoints.

Controlar a execução

Existem comandos que nos permitem controlar a execução de um programa:

Mostrar valores de variáveis

Podemos ver o valor de qualquer variável do programa com o comando print ou simplesmente p, por exemplo, supondo que estamos a executar um programa onde existe uma variável x:

           (gdb) print x
            $1 = 50

$1 é uma referência que pode ser usada no futuro para consultar valores anteriores da variável x. No caso da variável ser um apontador e quisermos examinar o conteúdo da posição de memória nela armazenada, teremos que usar o * tal como no C.
Ás vezes é útil poder ver o valor de uma variável sempre que existe um breakpoint, é feito um next ou um step. Para isso usamos o comando display:

           (gdb) display x
           1: x = 50
           (gdb) step
           1: x = 51
           ...  
A variável é associada a um índice, no caso anterior 1.

Alterar valores de variáveis

Para alterar o valor duma variável basta usar a instrução set, por exemplo:

           (gdb) set (x=49)

A variável x passa a ter o valor 49.

Sair do GDB

Para sair do gdb usamos o comando quit.

Utilizadores de emacs:
C-x 0

Exercício

O programa seguinte lê n inteiros n <= 20 e calcula a sua média:

#include <stdio.h>

int media(int [],float);

main(){

  int vec[20], n,i;
  printf("\n Quantos números (max.20)?:);
  scanf("%d",n);
  for(i=0;i<n;i++)
      scanf("%d",&vec[i]);
  printf("\n A media é: %d\n",media(vec,n));
}

int media(int vec[],int n){

  int i,s;
  for(i=0;i>n;i++);
   s+=vec[i];

  s = s/n;
  return s;
}
  1. Corrija eventuais erros de sintaxe e execute o programa.
  2. O comportamento do programa é o correcto? Use o gdb para corrigir os restantes erros.

Poderá encontrar um guia de referência rápida para o GDB aqui.

 
Jorge Coelho - ISEP 2002