Installing GDB
sudo apt-get install gdb
Common Debugging Commands
| Command Name | Command Abbreviation | Command Description |
|---|---|---|
| run | r | Run the program |
| continue | c | Continue running the program |
| break | b | Set a breakpoint |
| tbreak | tb | Set a temporary breakpoint |
| delete | del | Delete a breakpoint |
| enable | \ | Enable a breakpoint |
| disable | \ | Disable a breakpoint |
| info | \ | View current breakpoints/threads and other debugging information |
| next | n | Run to the next line, step over |
| step | s | Step into the function if there is a function call |
| until | u | Run until a specified line is reached |
| backtrace | bt | View the call stack |
| frame | f | Switch to the specified stack frame of the current call thread |
| p | Print the value of a variable | |
| list | l | View the source code |
| ptype | \ | View the variable type |
| thread | \ | Switch to the specified thread |
| finish | fi | End the current function call and return to the previous function |
| return | \ | End the current function call and return a specified value, returning to the previous function |
| jump | j | Jump to a specified line or address |
| disassemble | dis | View the assembly code |
| set args | \ | Set command line arguments |
| show args | \ | View the set command line arguments |
| watch | \ | Monitor whether the value of a variable or memory address changes |
| display | \ | Automatically output and monitor the variable or memory address when the program is interrupted |
| dir | \ | Redirect the location of source files |
| quit | q | Exit debugging |
Example
main.cpp:
#include <cstdio>
#include <iostream>
#include <typeinfo>
namespace MathUtils {
int add(int a, int b)
{
std::cout << "add(int, int) called" << std::endl;
std::cout << "a = " << a << ", b = " << b << std::endl;
return a + b;
}
template <typename T>
T max(T a, T b)
{
std::cout << "max " << typeid(T).name() << " called" << std::endl;
return a > b ? a : b;
}
// Explicit template instantiation
template int max<int>(int, int);
template double max<double>(double, double);
class Calculator {
public:
explicit Calculator(double init_value) : current_value(init_value) {}
void add(double value)
{
std::cout << "Calculator::add(double) called" << std::endl;
current_value += value;
}
private:
double current_value;
};
}
using namespace MathUtils;
int main()
{
int a = 5;
int b = 3;
add(a, b);
a = 10;
b = 20;
max(a, b);
double c = 3.14;
double d = 2.71;
max(c, d);
Calculator calc(10.0);
calc.add(5.0);
int val = 0;
for(; val < 10; val++)
{
std::cout << val << std::endl;
}
return 0;
}
Compile:
g++ main.cpp -g -o main
Debug:
gdb main
Breakpoints
Notify GDB to pause execution at specific locations in the program.
Line Breakpoints
- • break line
- • break file:line
Function Breakpoints
- • break function
- • break file:functionSetting breakpoints in C++:
- • break namespace::function // Namespace function
- • break class::function // Class method
- • break function(T, T) // Function template, specific type must be specified
Address Breakpoints
Set a breakpoint at a specified virtual address, used when the program does not have debugging information
- • break *address
Conditional Breakpoints
Pause execution when specific conditions are met, basic syntax:
- • break line if [condition expression]
- • break function if [condition expression]Valid C condition statements can be used for conditional breakpoint expressions, which must evaluate to a boolean value:
- • Equality, logical, and inequality operators (<, <=, >, >=, ==, !=, &&, ||, etc.), for example:break 18 if string==”hello” && i < 0
- • Bitwise and shift operators (&, |, ^, <<, >>, etc.), for example:break 18 if (x & 0x1) == 1
- • Arithmetic operators (+, -, *, /, etc.), for example:break 18 if (x + y) > 10
- • Function calls, the function must be linked in the program:
- • Personal function: break 18 if is_zero(x)
- • Library function: break 18 if strlen(string) == 0
- • Parentheses can be used to control precedence, for example:break 18 if (x > 0) && (y < 0)
Normal breakpoint conditions can be converted to conditional breakpoints, syntax format:condition [breakpoint number] [condition expression]Assuming there is a breakpoint 3
- • Add condition, i==3:cond 3 i == 3
- • Delete condition:cond 3
Example:
(gdb) break 42 # Set line breakpoint
Breakpoint 1 at 0x400a2a: file main.cpp, line 42.
(gdb) break main.cpp:43 # Set file line breakpoint
Breakpoint 2 at 0x400a31: file main.cpp, line 43.
(gdb) break main # Set function breakpoint, same for other ordinary functions
Breakpoint 3 at 0x400a1b: file main.cpp, line 41.
(gdb) break MathUtils::add # Set namespace function breakpoint
Breakpoint 4 at 0x4009a4: file main.cpp, line 8.
(gdb) break MathUtils::Calculator::add # Set class method breakpoint
Breakpoint 5 at 0x400cad: file main.cpp, line 29.
(gdb) break MathUtils::max<int>(int, int) # Set function template breakpoint
Breakpoint 6 at 0x400bb2: file main.cpp, line 16.
(gdb) break 69 if val==5 # Set conditional breakpoint
No line 69 in the current file.
Make breakpoint pending on future shared library load? (y or [n]) N
(gdb) break 60 if val==5
Breakpoint 7 at 0x400ae4: file main.cpp, line 60.
(gdb) info break # View breakpoint information
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400a2a in main()
at main.cpp:42
2 breakpoint keep y 0x0000000000400a31 in main()
at main.cpp:43
3 breakpoint keep y 0x0000000000400a1b in main()
at main.cpp:41
4 breakpoint keep y 0x00000000004009a4 in MathUtils::add(int, int) at main.cpp:8
5 breakpoint keep y 0x0000000000400cad in MathUtils::Calculator::add(double) at main.cpp:29
6 breakpoint keep y 0x0000000000400bb2 in MathUtils::max<int>(int, int) at main.cpp:16
7 breakpoint keep y 0x0000000000400ae4 in main()
at main.cpp:60
stop only if val==5
(gdb) run
Starting program: /home/alientek/Desktop/test/gdb/main
Breakpoint 3, main () at main.cpp:41 # Breakpoint 3 hit
41 {
(gdb) c
Continuing.
Breakpoint 1, main () at main.cpp:42 # Breakpoint 1 hit
42 int a = 5;
(gdb) c
Continuing.
Breakpoint 2, main () at main.cpp:43 # Breakpoint 2 hit
43 int b = 3;
(gdb) c
Continuing.
Breakpoint 4, MathUtils::add (a=5, b=3) at main.cpp:8 # Breakpoint 4 hit
8 std::cout << "add(int, int) called" << std::endl;
(gdb) c
Continuing.
add(int, int) called
a = 5, b = 3
Breakpoint 6, MathUtils::max<int> (a=10, b=20) at main.cpp:16 # Breakpoint 6 hit
16 std::cout << "max " << typeid(T).name() << " called" << std::endl;
(gdb) c
Continuing.
max i called
max d called
Breakpoint 5, MathUtils::Calculator::add (this=0x7fffffffdca0, value=5)
at main.cpp:29
29 std::cout << "Calculator::add(double) called" << std::endl;
(gdb) c
Continuing.
Calculator::add(double) called
0
1
2
3
4
Breakpoint 7, main () at main.cpp:60 # Breakpoint 7 hit
60 std::cout << val << std::endl;
(gdb) c
Continuing.
5
6
7
8
9
[Inferior 1 (process 6956) exited normally] # Program exited normally
Breakpoint Commands
Execute a series of commands at breakpoints
- • commands [breakpoint number][command1][command2]…end
Set a breakpoint at line 50 in main.cpp:
(gdb) break main.cpp:44
Breakpoint 8 at 0x400a38: file main.cpp, line 44.
(gdb) info break
Num Type Disp Enb Address What
8 breakpoint keep y 0x0000000000400a38 in main()
Example 1, automatically print variable values:
(gdb) commands 8
Type commands for breakpoint(s) 8, one per line.
End with a line saying just "end".
>printf "a = %d, b = %d\n", a, b
>end
(gdb) run
Starting program: /home/alientek/Desktop/test/gdb/main
Breakpoint 8, main () at main.cpp:44
44 add(a, b);
a = 5, b = 3
Example 2, modify the value of variable a:
(gdb) commands 8
Type commands for breakpoint(s) 8, one per line.
End with a line saying just "end".
>set variable a = 0
>continue
>end
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/alientek/Desktop/test/gdb/main
Breakpoint 8, main () at main.cpp:44
44 add(a, b);
add(int, int) called
a = 0, b = 3 # The value of a has been modified
Check the breakpoint information, you can see that breakpoint 8 contains the commands added above:
(gdb) info break
Num Type Disp Enb Address What
8 breakpoint keep y 0x0000000000400a38 in main()
at main.cpp:44
breakpoint already hit 1 time
set variable a = 0
continue
Example 3, print the call stack:
(gdb) delete 8 # Delete breakpoint 8
(gdb) info break
No breakpoints or watchpoints.
(gdb) break main.cpp:46 # Set a breakpoint at line 46 in main.cpp, breakpoint number 9
Breakpoint 9 at 0x400a47: file main.cpp, line 46.
(gdb) commands 9 # Add commands for breakpoint 9
Type commands for breakpoint(s) 9, one per line.
End with a line saying just "end".
>silent # Silent mode, do not print breakpoint information
>backtrace # Print the call stack
>info locals # Print local variables
>end
(gdb) run # Run the program
Starting program: /home/alientek/Desktop/test/gdb/main
add(int, int) called
a = 5, b = 3
#0 main () at main.cpp:46 # Call stack
a = 5 # Local variable
b = 3 # Local variable
c = 2.0733524115605412e-317 # Local variable
d = 6.9533558074002266e-310 # Local variable
calc = {current_value = 2.07389786003355e-317} # Local variable
val = 0 # Local variable
Example 4, use GDB’s define command to create a macro to print the values of variables a and b:
(gdb) clear main.cpp:46 # Delete breakpoint at line 46 in main.cpp, breakpoint number 9
Deleted breakpoint 9
(gdb) break main.cpp:44 # Set a breakpoint at line 44 in main.cpp
Breakpoint 1 at 0x400abc: file main.cpp, line 51.
(gdb) info break # View breakpoint information
Num Type Disp Enb Address What
10 breakpoint keep y 0x0000000000400a38 in main()
at main.cpp:44
(gdb) define printf_a_b # Define macro
Type commands for definition of "printf_a_b".
End with a line saying just "end".
>printf$arg0, $arg1, $arg2 # Equivalent to printf "formatted string", variable a, variable b,
# here $arg0, $arg1, $arg2 are macro parameters, supporting up to 10 parameters
>end
(gdb) command 10 # Add commands for breakpoint 10
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>silent
>printf_a_b "breakpoint1 a = %d, b = %d\n" a b # Use macro to print the values of variables a and b
>end
(gdb) run
Starting program: /home/alientek/Desktop/test/gdb/main
breakpoint1 a = 5, b = 3 # Output values of a and b
Deleting Breakpoints
In the previous examples, there have been multiple commands to delete breakpoints, summarized as follows:
- • delete # Delete all breakpoints
- • delete [breakpoint number] # Delete specified breakpoint
- • clear [location] # Delete breakpoint at specified location, location can be: line number, function name, filename:line number, filename:function name, address
- • disable [breakpoint number] # Disable specified breakpoint
- • enable [breakpoint number] # Enable specified breakpoint
Resuming Execution
continue
continue abbreviated as c, has been attempted in the above examples.This command allows GDB to resume program execution until the next breakpoint is triggered or the program ends.
step and next for single-step debugging
step abbreviated as s, allows GDB to enter the function and execute line by line, entering the function if there is a function call.next abbreviated as n, allows GDB to execute line by line, not entering the function if there is a function call, stopping at the first statement after the function call.step example, pause at line 44, and enter the add function, executing line by line:
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400a38 in main()
at main.cpp:44
(gdb) run
Starting program: /home/alientek/Desktop/test/gdb/main
Breakpoint 1, main () at main.cpp:44
44 add(a, b);
(gdb) s
MathUtils::add (a=5, b=3) at main.cpp:8
8 std::cout << "add(int, int) called" << std::endl;
(gdb) s
add(int, int) called
9 std::cout << "a = " << a << ", b = " << b << std::endl;
(gdb) s
a = 5, b = 3
10 return a + b;
(gdb) s
11 }
(gdb) s
main () at main.cpp:46
46 a = 10;
next example, pause at line 44, treating the add function as a single line of code, executing line by line:
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/alientek/Desktop/test/gdb/main
Breakpoint 1, main () at main.cpp:44
44 add(a, b);
(gdb) n
add(int, int) called
a = 5, b = 3
46 a = 10;
finish
finish abbreviated as fin, allows GDB to execute the current function and return to the place where the function was called.Example:
(gdb) break main.cpp:44 # Set a breakpoint at line 44 in main.cpp
Breakpoint 1 at 0x400a38: file main.cpp, line 44.
(gdb) r
Starting program: /home/alientek/Desktop/test/gdb/main
Breakpoint 1, main () at main.cpp:44 # Pause at line 44
44 add(a, b);
(gdb) step # Step into the add function
MathUtils::add (a=5, b=3) at main.cpp:8
8 std::cout << "add(int, int) called" << std::endl;
(gdb) finish # Execute finish command, complete the add function, and return to the main function
Run till exit from #0 MathUtils::add (a=5, b=3) at main.cpp:8
add(int, int) called
a = 5, b = 3
main () at main.cpp:46
46 a = 10;
Value returned is $1 = 8
until
until abbreviated as u, is usually used to exit loops or skip the remaining part of the current function.Example:
(gdb) break main.cpp:57 # Set a breakpoint at line 57 in main.cpp
Breakpoint 1 at 0x400ad7: file main.cpp, line 57.
(gdb) run
Starting program: /home/alientek/Desktop/test/gdb/main
add(int, int) called
a = 5, b = 3
max i called
max d called
Calculator::add(double) called
Breakpoint 1, main () at main.cpp:57 # Pause at line 57
57 int val = 0;
(gdb) next # Execute line by line
58 for(; val < 10; val++)
(gdb) next
60 std::cout << val << std::endl;
(gdb) next
0
58 for(; val < 10; val++)
(gdb) print val # Print the value of variable val
$1 = 0
(gdb) until # Execute until command
1
2
3
4
5
6
7
8
9
63 return 0; # Reached the next line of source code outside the loop
(gdb) next
64 }(gdb)
__libc_start_main (main=0x400a13 <main()>, argc=1, argv=0x7fffffffdda8, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdd98) at ../csu/libc-start.c:325
325 ../csu/libc-start.c: No such file or directory.
(gdb)
[Inferior 1 (process 6689) exited normally] # Program exited normally
Note that when using until, if there are breakpoints inside the loop, it cannot exit the loop.
References
- 【The Art of Software Debugging (Matt Lavoie et al.)】. Translated by Zhang Yun.
- I hope you enjoyed this article. You can follow the public account for more programming knowledge to be shared in the future.