gdb Command on Linux: Debug and Inspect Compiled Programs with GCC
The gdb command in Linux is a very useful tool for debugging software compiled with GCC.
Using the gdb debugger for the first time
For the debugger to work, the software must be compiled with the "-g" option of gcc, so that the compiler will provide debugging information in the object code.
Example:
$ gcc –wall –g principal.c rede.c interface.c –o pingnovo
The main idea for debugging a program is to insert a breakpoint at the point where you want to start debugging at a specific line N of the code.
The breakpoint makes the program execution stop at a specific point you want to examine more carefully.
After inserting the breakpoint, you should run the program inside gdb and advance through execution, checking the parameters passed to functions, the type and content of variables, until the error is found. Then, you fix the error in the source code and recompile the program.
Using gdb is simple:
# gdb programa-executávelGNU gdb 5.3.92Copyright 2003 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i586-suse-linux"...(gdb)
Its interface is command-based in Linux with relatively simple syntax.
Commands can be written in full or abbreviated form, where generally only their first letters are used. Parameters such as line numbers and variable names are passed immediately after the command name.
Let's look at the most important commands:
To insert a breakpoint at a specific line of code:
break N
or
b N
Where N is the line of code where you want to stop program execution. For this, it may be necessary to view the program's source code.
To remove all breakpoints:
delete
or
d
To run the program until it hits the first breakpoint:
run
or
r
To list the program's source code:
list
or
l
To execute the next instructions of the program. An instruction can be understood as a function:
next N
or
n N
Where N is the number of instructions.
To execute the next N lines after the breakpoint:
step N
or
s N
To terminate the program:
kill
or
k
To display information about a variable's type:
what variável
or
w variável
To display the content of a variable:
print variável
or
p variável
To view the state of a variable at each step of execution:
display variável
To view the content of all instantiated variables:
info locals
To see the program's registers:
info registers
To view the program's assembly code:
disassemble
To view the recursion stack:
backtrace
or
bt
To get help regarding a command:
help comando
or
h comando
To exit gdb:
quit
or
q
Example of debugging a program
Debugging programs without using appropriate tools can be an exhausting task and often impossible. To help with this task, here is an example of the procedure to discover problems using GDB.
The following example program was made to trigger a floating point calculation error:
#include <stdio.h>float calculo(int numero1, int numero2){ int diferenca; float resultado; diferenca = numero1 - numero2; resultado = numero1 / diferenca; return resultado;}int main(int argc, char *argv[]){ int valor, divisor, i; float resultado, total; valor = 10.1; divisor = 6; total = 0; for(i = 0; i < 10; i++) { resultado = calculo(valor, divisor); total += resultado; printf("%d dividido por %d é %f. A soma dos resultados é %f.\n", valor, valor-divisor, resultado,total); divisor++; valor--; }return 0;}
To compile this program saved as "erro.c":
$ gcc –g erro.c –o erro
The "-g" option compiles the program with the necessary information for debugging.
This program should execute a loop ten times and calculate the accumulated value of successive divisions. However, when running it, an error will abort its execution:
$ ./erro10 dividido por 4 é 2.000000. A soma dos resultados é 2.000000.9 dividido por 2 é 4.000000. A soma dos resultados é 6.000000.Floating point exception
To do the debugging it is necessary to run the program through GDB:
$ gdb erroGNU gdb 5.3.92Copyright 2003 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i586-suse-linux"...(gdb)
The program can be run inside GDB with the "run" command:
(gdb) runStarting program: /root/sistemas/erro10 dividido por 4 é 2.000000. A soma dos resultados é 2.000000.9 dividido por 2 é 4.000000. A soma dos resultados é 6.000000.Program received signal SIGFPE, Arithmetic exception.0x0804835e in calculo (numero1=8, numero2=8) at gdb.c:77 resultado = numero1 / diferenca;
GDB indicated that the program performed an illegal math operation on line 7 precisely in the calculo function:
The values of variables numero1 and numero2 are 8. We can list the program's source code to see what it is doing with the "list" command:
(gdb) list2 float calculo(int numero1, int numero2)3 {4 int diferenca;5 float resultado;6 diferenca = numero1 - numero2;7 resultado = numero1 / diferenca;8 return resultado;9 }10 int main(int argc, char *argv[])11 {
The list command will list the code 10 lines at a time. It can be repeated until all the code is displayed.
As a first step, it is interesting to examine the contents of the variables with the "print" command:
(gdb) print numero1$1 = 8(gdb) print numero2$2 = 8(gdb) print diferenca$3 = 0
On line 7 of the program where the error occurred, you can verify that the operation "resultado = numero1 / diferença". Analyzing the values of the variables and the instruction, you can deduce that the program is trying to perform division by zero.
We can continue the program execution with the "continue" command:
(gdb) continueContinuing.Program terminated with signal SIGFPE, Arithmetic exception.The program no longer exists.
Since the division by zero error aborts execution, the program will not continue. It will be necessary to use breakpoints and run the program again. It is interesting to set the breakpoint in the main function before the call to the calculo function.
(gdb) list10 int main(int argc, char *argv[])11 {12 int valor, divisor, i;13 float resultado, total;14 valor = 10.1;15 divisor = 6;16 total = 0;17 for(i = 0; i < 10; i++)18 {19 resultado = calculo(valor, divisor);20 total += resultado;21 printf("%d dividido por %d é %f. A soma dos resultados é %f.\n", = valor, valor-divisor, resultado,total);22 divisor++;23 valor--;24 }25 return 0;
We can set a breakpoint at line 12 at the beginning of the main function and run the program again:
(gdb) break 12Breakpoint 1 at 0x8048384: file gdb.c, line 12.(gdb) runStarting program: /root/sistemas/erroBreakpoint 1, main (argc=1, argv=0xbfffd874) at gdb.c:1414 valor = 10.1;
Execution will stop at line 14 which contains a meaningful instruction after line 12. We can advance the execution line by line with the "next" command:
(gdb) next15 divisor = 6;(gdb) next16 total = 0;(gdb) next17 for(i = 0; i < 10; i++)
The contents of variables can be displayed with the "print" command followed by the variable name:
(gdb) print valor$5 = 10(gdb) print divisor$6 = 6
The value of all instantiated variables can be seen with the "info locals" command:
(gdb) info localsvalor = 10divisor = 6i = 0resultado = -1.99878407total = 0
The next step is to run the program line by line until the contents of the variables valor and divisor are 8. The "display" command allows the contents of a variable to be displayed at each processed instruction:
(gdb) display valor1: valor = 10(gdb) display divisor2: divisor = 6
The advancement of instructions can be done with the "next" command:
(gdb) next20 total += resultado;2: divisor = 61: valor = 10(gdb) next21 printf("%d dividido por %d é %f. A soma dos resultados é %f.\n", valor, valor-divisor, resultado,total);2: divisor = 61: valor = 10(gdb) next10 dividido por 4 é 2.000000. A soma dos resultados é 2.000000.22 divisor++;2: divisor = 61: valor = 10(gdb) next23 valor--;2: divisor = 71: valor = 10(gdb) next17 for(i = 0; i < 10; i++)2: divisor = 71: valor = 9(gdb) next19 resultado = calculo(valor, divisor);2: divisor = 71: valor = 9(gdb) next20 total += resultado;2: divisor = 71: valor = 9(gdb) next21 printf("%d dividido por %d é %f. A soma dos resultados é %f.\n", valor, valor-divisor, resultado,total);2: divisor = 71: valor = 9(gdb) next9 dividido por 2 é 4.000000. A soma dos resultados é 6.000000.22 divisor++;2: divisor = 71: valor = 9(gdb) next23 valor--;2: divisor = 81: valor = 9(gdb) next17 for(i = 0; i < 10; i++)2: divisor = 81: valor = 8
At this point, the calculo function will return division by zero. The variable value can be changed at runtime to work around the error with the "set" command:
(gdb) info localsvalor = 8divisor = 8i = 1resultado = 4total = 6(gdb) set valor = 10(gdb) info localsvalor = 10divisor = 8i = 1resultado = 4total = 6
The program will continue execution until it encounters another division by zero.
(gdb) next19 resultado = calculo(valor, divisor);2: divisor = 81: valor = 10(gdb) next20 total += resultado;2: divisor = 81: valor = 10(gdb) next21 printf("%d dividido por %d é %f. A soma dos resultados é %f.\n", valor, valor-divisor, resultado,total);2: divisor = 81: valor = 10(gdb) next10 dividido por 2 é 5.000000. A soma dos resultados é 11.000000.22 divisor++;2: divisor = 81: valor = 10(gdb) next23 valor--;2: divisor = 91: valor = 10(gdb) next17 for(i = 0; i < 10; i++)2: divisor = 91: valor = 9(gdb) next19 resultado = calculo(valor, divisor);2: divisor = 91: valor = 9(gdb) nextProgram received signal SIGFPE, Arithmetic exception.0x0804835e in calculo (numero1=9, numero2=9) at gdb.c:77 resultado = numero1 / diferenca;
In this example's case, the program has the variables declared as integers, not allowing the remainder of a division.
GDB is a powerful program debugger. We encourage you to install a graphical interface for it to facilitate its use. There are other debuggers available as well.
Learn much more about Linux in our online course. You can enroll here. If you already have an account, or want to create one, just log in or create your user here.
Did you like it? Share
That was just one piece. The course teaches the whole path — from your first command to exam day.