Guia basico GDB

De MediaWiki do Campus São José
Revisão de 14h44min de 12 de agosto de 2014 por Msobral (discussão | contribs) (→‎Passo a passo)
Ir para navegação Ir para pesquisar

Traduzido de Tutorial of gcc and gdb.

Introdução

'gdb é um depurador (debugger) feito pelo projeto GNU. gdb pode executar passo a passo o seu programa linha por linha e mesmo instrução por instrução. Com ele se consegue também observar o valor de qualquer variável em tempo de execução. Por fim, ele ajuda a identificar o lugar e o motivo que causou um erro de execução do programa.

Uso básico

Todo programa a ser depurado com gdb precisa ser compilado pelo gcc com a opção -g. Isso é demonstrado abaixo com um pequeno programa de exemplo.

  1. Copie este programa para o arquivo exemplo.c:
    #include <stdio.h>
    #include <string.h>
    
    int main() {
      int n;
      char nome[32];
    
      printf("Digite seu nome: ");
      fgets(nome, 32, stdin);
      nome[strlen(nome)] = 0;
      for (n=strlen(nome); n >= 0; n--) {
        printf("%c", nome[n]);
      }
      return 0;
    }
    
  2. Compile-o da seguinte forma:
    gcc -g -o exemplo exemplo.c
    
  3. Use o gdb para depurá-lo:
    gdb ./exemplo
    
    • ... o que vai mostrar uma apresentação do gdb na sua tela:
      GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
      Copyright (C) 2012 Free Software Foundation, Inc.
      License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
      This is free software: you are free to change and redistribute it.
      There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
      and "show warranty" for details.
      This GDB was configured as "x86_64-linux-gnu".
      For bug reporting instructions, please see:
      <http://bugs.launchpad.net/gdb-linaro/>...
      Lendo símbolos de /home/aluno/exemplo...concluído.
      (gdb)
      
  4. Antes de iniciar a execução do programa, defina ao menos um ponto de parada (breakpoint). O gdb para a execução nesse ponto, a partir do qual se pode executar passo-a-passo. Um ponto de parada pode ser uma função ou uma linha do programa. No exemplo, o ponto de parada foi definido como sendo a função main:
    (gdb) break main
    Ponto de parada 1 at 0x40063c: file exemplo.c, line 4.
    
  5. Execute o programa, notando que a execução para no ponto de parada que foi definido:
    (gdb) run
    Starting program: /home/aluno/exemplo 
    
    Breakpoint 1, main () at exemplo.c:4
    4	int main() {
    
  6. Para avançar uma linha do programa, use o comando next. Após esse comando é mostrada a próxima linha do programa a ser executada:
    (gdb) next
    8	  printf("Digite seu nome: ");
    
  7. Para terminar a depuração, use o comando quit:
    (gdb) quit
    A debugging session is active.
    
    	Inferior 1 [process 15861] will be killed.
    
    Quit anyway? (y or n) 
    Y
    

Execução de um programa que pede argumentos de linha de comando

Devem-se informar os argumentos do programa em seguida ao comando run. Ex: se o programa exemplo pedisse um argumento:

(gdb) run arg1

... e se pedisse dois argumentos:

(gdb) run arg1 arg2

Passo a passo

A execução passo-a-passo pode ser feita com os comandos next ou step. Com next executa-se uma linha de código, sem entrar em funções que porventura sejam chamadas. Com step executa-se uma linha, porém entrando em funções chamadas. Por exemplo, seja o programa exemplo1.c abaixo:

#include <stdio.h>
#include <string.h>

void mostraInvertido(char * texto) {
  int n;

  for (n=strlen(texto); n > 0; n--) {
    printf("%c", texto[n-1]);
  }
  puts("");
}
 
int main() {
  char nome[32];
 
  printf("Digite seu nome: ");
  fgets(nome, 32, stdin);
  nome[strlen(nome)-1] = 0;
  mostraInvertido(nome);
  return 0;
}

Se a depuração passo-a-passo for realizada com next:

(gdb) break main
Ponto de parada 1 at 0x4006f4: file exemplo1.c, line 13.
(gdb) run
Starting program: /home/aluno/exemplo1 

Breakpoint 1, main () at ex1.c:13
13	int main() {
(gdb) next
16	  printf("Digite seu nome: ");
(gdb) next
17	  fgets(nome, 32, stdin);
(gdb) next
Digite seu nome: maneca
18	  nome[strlen(nome)-1] = 0;
(gdb) next
19	  mostraInvertido(nome);
(gdb) next
acenam
20	  return 0;
(gdb) next
21	}
(gdb) next
0x00007ffff7a3b78d in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
(gdb)

Note o que acontece se for usado step ao executar a linha 19 (mostraInvertido(nome)). O depurador começa a executar dentro da funjção mostraInvertido:

(gdb) run
Starting program: /home/msobral/tmp/ex1 

Breakpoint 1, main () at ex1.c:13
13	int main() {
(gdb) next
16	  printf("Digite seu nome: ");
(gdb) next
17	  fgets(nome, 32, stdin);
(gdb) next
Digite seu nome: maneca
18	  nome[strlen(nome)-1] = 0;
(gdb) next
19	  mostraInvertido(nome);
(gdb) step
mostraInvertido (texto=0x7fffffffe030 "maneca") at ex1.c:7
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) next
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) next
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) next
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) next
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) next
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) next
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
10	  puts("");
(gdb) next
acenam
11	}
(gdb) next
main () at exemplo1.c:20
20	  return 0;
(gdb) next
21	}
(gdb) next
0x00007ffff7a3b78d in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
(gdb)

Executando até o o final de uma função

Estando no passo-a-passo, pode-se executar até o final da função corrente com o comando finish. Assim o programa executa direto até chegar o final da função, e logo após retornar volta-se ao passo-a-passo:

(gdb) run
Starting program: /home/aluno/exemplo1 

Breakpoint 1, main () at exemplo1.c:13
13	int main() {
(gdb) next
16	  printf("Digite seu nome: ");
(gdb) next
17	  fgets(nome, 32, stdin);
(gdb) next
Digite seu nome: maneca
18	  nome[strlen(nome)-1] = 0;
(gdb) next
19	  mostraInvertido(nome);
(gdb) step
mostraInvertido (texto=0x7fffffffe030 "maneca") at ex1.c:7
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) next
7	  for (n=strlen(texto); n > 0; n--) {
(gdb) next
8	    printf("%c", texto[n-1]);
(gdb) finish
Run till exit from #0  mostraInvertido (texto=0x7fffffffe030 "maneca")
    at ex1.c:8
acenam
main () at exemplo1.c:20
20	  return 0;
(gdb) next
21	}
(gdb) next
0x00007ffff7a3b78d in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
(gdb)

Saindo do passo-a-passo

Pode-se sair do passo-a-passo com o comando continue. Com ele o programa volta a executar continuamente, até chegar a um ponto de parada ou terminar.

(gdb) run
Starting program: /home/aluno/exemplo1

Breakpoint 1, main () at exemplo1.c:13
13	int main() {
(gdb) next
16	  printf("Digite seu nome: ");
(gdb) next
17	  fgets(nome, 32, stdin);
(gdb) continue
Continuando.
Digite seu nome: maneca
acenam
[Inferior 1 (process 17002) exited normally]
(gdb)

To start running and debugging the program, we can simply type the "run" command after the (gdb) prompt as below:

(gdb) run

If the program takes arguments such as "garbage arg_1 arg_2", we may start running the program with these arguments as:

(gdb) run arg_1 arg_2