Essa é uma revisão anterior do documento!
Para quem programa em ambiente Linux existe uma ferramenta de debug muito importante o software gdb. Ele permite realizar certos debug em programas C. Vamos a um exemplo de um Ola Mundo e abri-lo no gdb.
#include <stdio.h> int main() { printf("Ola mundo\n"); return 0; }
Para compilar com suporte a simbolos que o gdb precisa para realizar o debug.
gcc -g -o olamundo olamundo.c
Para entrar no gdb e necessário somente passar como parametro o nome do programa no nosso caso de exemplo seria o nome olamundo.
ricardobarbosa@isadora:~/dev/c/pilha$ gdb olamundo GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 Copyright (C) 2014 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". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from olamundo...done. (gdb) (gdb) (gdb)
Iremos cair no prompt de comando do gdb. O gdb funciona como um médico analisando um paciente, o paciente no nosso caso e o programa olamundo. Outro conceito importante do gdb é o breakpoint. O que seria um breakpoint seguindo a tradução seria um ponto de parada ou ponto de interrupção, ou seja, criaremos um ponto de parada onde nos executaremos o programa e quando ele chegar naquele ponto de parada irá parar e esperar interação do usuário, para verificar o conteúdo de uma variavel ou visualizar endereços de memória, etc.
Vamos criar um breakpoint na função main.
(gdb) break main Breakpoint 1 at 0x400531: file olamundo.c, line 5. (gdb)
Agora iremos executar nosso programa e ver ele parar no breakpoint na função main.
(gdb) run Starting program: /home/ricardobarbosa/dev/c/pilha/olamundo Breakpoint 1, main () at olamundo.c:5 5 printf("Ola mundo\n"); (gdb)
podemos também visualizar o código do programa através do comando list.
(gdb) list 1 #include <stdio.h> 2 3 int main() 4 { 5 printf("Ola mundo\n"); 6 return 0; 7 } (gdb)
Para executar passo-a-passo temos dois comandos
Então executaremos a próxima instrução.
(gdb) next Ola mundo 6 return 0; (gdb)
Repare que ele executou e exibiu a mensagem ola mundo e mostrou a próxima instruçao de return 0 o qual indica sucesso. Se continuarmos dando next executaremos todo o programa e o mesmo será finalizado.
(gdb) next Ola mundo 6 return 0; (gdb) next 7 } (gdb) next __libc_start_main (main=0x40052d <main>, argc=1, argv=0x7fffffffdcd8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdcc8) at libc-start.c:321 321 libc-start.c: No such file or directory. (gdb)
Além da execução de instruções passo-a-passo podemos ver o contéudo de variaveis. Vamos utilizar o seguinte código para exemplificar isto.
(gdb) break main Breakpoint 1 at 0x4004f1: file olamundo2.c, line 5. (gdb) run Starting program: /home/ricardobarbosa/dev/c/pilha/olamundo2 Breakpoint 1, main () at olamundo2.c:5 5 int a=10; (gdb) n 6 int b=10; (gdb) print a $1 = 10 (gdb) print b $2 = 0 (gdb) n 8 c=a+b; (gdb) print b $3 = 10 (gdb) n 9 return 0; (gdb) print c $4 = 20 (gdb)
Existe alguns comandos para verificar variaveis.
O comando “info variables” para listar os nomes de todas as variaveis globais e estatica.
O comando “info locals” para listar as váriaveis locais que estão atualmente na pilha.
(gdb) info locals a = 10 b = 10 c = 20 (gdb)
O comando “info args” para listar os argumentos passados para o programa.
O comando “info frame” exibe informações sobre a pilha
(gdb) info frame Stack level 0, frame at 0x7fffffffdc00: rip = 0x40050a in main (olamundo2.c:9); saved rip = 0x7ffff7a36f45 source language c. Arglist at 0x7fffffffdbf0, args: Locals at 0x7fffffffdbf0, Previous frame's sp is 0x7fffffffdc00 Saved registers: rbp at 0x7fffffffdbf0, rip at 0x7fffffffdbf8 (gdb)
O comando “backtrace” exibe um rastreio da pilha
(gdb) backtrace #0 foo (x=255, y=255) at exemplo01.c:14 #1 0x0000000000400778 in main () at exemplo01.c:50 (gdb)
No comando acima mostra o frame da pilha para função main e função foo
Para navegar pela frame da pilha
gdb> frame 1
É possível também visualizar o conteúdo de uma posição de memória através do comando “x”. O comando “x” segue uma sintaxe bem simples
x/<contagem><formato><unidade tamanho> endereço
Exemplo queremos visualizar o conteudo do registrador SP em hexadecimal, decimal e decimal sem sinal(unsigned).
(gdb) x/x $rsp 0x7fffffffdb20: 0x00000001 (gdb) x/d $rsp 0x7fffffffdb20: 1 (gdb) x/u $rsp 0x7fffffffdb20: 1 (gdb)
Para verificar a instrução armazenada no registrador RIP
(gdb) x/i $rip => 0x4005a1 <foo+180>: movabs $0x406fe00000000000,%rax (gdb)
3. x/100x $sp - show stack memory
You need to use gdb's memory-display commands. The basic one is x, for examine. There's an example on the linked-to page that uses
gdb> x/4xw $sp
to print “four words (w ) of memory above the stack pointer (here, $sp) in hexadecimal (x)”. The quotation is slightly paraphrased.
############################
Try using ddd. ddd manual
Ok. Maybe I elaborate a little. I use it like this.
compile my program with debug symbols:
gcc -g program.c -o program
run ddd:
ddd program
In gui you can do all sorts of things, view machine code, view memory, etc. . Look around. In manual there is also a section of examining stack. ddd provides good interface for you to examine C program