domingo, 25 de março de 2012

Usando o GDB

olá pessoal, hoje vamos tentar usar o GDB, uma ferramenta de debug muito útil no desenvolvimento.
Para demostrar o seu uso, vamos fazer um pequeno programa e uma função para somar todos os elementos de uma matriz.

Nosso código fonte:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main()
  4. {
  5. int matriz[5] = {1,2,5,3};
  6. int * result;
  7. somaArray(matriz,5,result);
  8. printf("\n\tResult: %d\n", *result);
  9. return 1;
  10. }
  11. void somaArray(int * m, int size, int * result)
  12. {
  13. int acul=0;
  14. int x;
  15. for(x=0;x<size;x++)
  16. {
  17. acul+=m[x];
  18. }
  19. *result = acul;
  20. }

Bom, obviamente esse código tem um erro, não inicializamos o ponteiro “result” assim quando formos escrever nele vamos receber um “segmentation fault”

Bom mas por enquanto vamos fazer de conta que não tem problema e vamos compilar nosso código fonte com o seguinte comando:

eduardo@debian:~/Documents/programas/gdb$ gcc -o gdbTest gdbTest.c

Vamos executar:

eduardo@debian:~/Documents/programas/gdb$ ./gdbTest

E vamos ver o resultado da soma!!!!!
Segmentation fault

É, ainda não foi dessa vez. Bom, vamos pedir ajuda ao gdb. Aqui eu já estou com o gdb instalado. Se você não tem ele instalado você pode rodar o comando:
apt-get install gdb

Mas não vamos cobrir aqui detalhes da instalação. Nosso objetivo, agora, é usar.

Primeiro passo: vamos compilar nosso programa novamente, com a opção “-g”, assim, o gdb teerá melhores condições de analisar nosso código e nos permitirá, por exemplo imprimir a linha do SIGSEGV.

Vamos lá:
eduardo@debian:~/Documents/programas/gdb$ gcc -g -o gdbTest gdbTest.c

Segundo passo: rodar com o gdb

eduardo@debian:~/Documents/programas/gdb$ gdb ./gdbTest
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 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://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/eduardo/Documents/programas/gdb/gdbTest...done.
(gdb)

Vai ficar piscando o cursor. Apenas digitamos: run

(gdb) run
Starting program: /home/eduardo/Documents/programas/gdb/gdbTest

Program received signal SIGSEGV, Segmentation fault.
0x000000000040059e in somaArray (m=0x7fffffffe280, size=5, result=0x0)
at gdbTest.c:23
23 *result = acul;
(gdb)

Já recebemos o nosso “SIGSEGV”, bom veja que ele já nos informou a linha que isso ocorreu – linha 23 – e em qual função – somaArray – veja que ele nos passou os argumentos da função, veja que o primeiro parâmetro é um ponteiro, e realmente tem um endereço ali. O segundo parâmetro é um int, e realmente tem o valor 5 que estamos passando, mas e o ponteiro result? Veja que ele é nulo, e na linha 23 estamos tentando escrever nele!!! então achamos a causa do sigsegv.

Se você desejar ver quem chamou a função somaArray, você pode digital o comando bt (backtrace). Imagine que você poderia ter no main várias chamadas para essa função no main. Veja que é na linha 23 que o problema acontece, mas essa linha está certa, o problema é que já estamos recebendo o ponteiro nulo!!!

então:
(gdb) bt
#0 0x000000000040059e in somaArray (m=0x7fffffffe280, size=5, result=0x0)
at gdbTest.c:23
#1 0x0000000000400539 in main () at gdbTest.c:7
(gdb)

Agora vamos no main na linha 7 e ver como é a chamada.
somaArray(matriz,5,result);

bom a variável matriz está inicializada corretamente. O parâmetro size já é 5, então está certo. O result, logo acima, na linha 6 foi declarado:
int * result;

Mas não foi inicializado!!! e logo abaixo já o usamos.

Bom, achamos o problema, agora corrigimos:

Vamos alterar a linha 6 para:
int * result = (int *) malloc(sizeof(int));

vamos compilar novamente, pode ser sem a flag “-g”.

eduardo@debian:~/Documents/programas/gdb$ gcc -o gdbTest gdbTest.c

uardo@debian:~/Documents/programas/gdb$ ./gdbTest

Result: 11
eduardo@debian:~/Documents/programas/gdb$

Resolvido!!!!