If you haven’t read the previous article, I suggest you check it out: Debugging C++ Programs Using GDB in Command Line (Part One)
This article supplements the GDB debugging that wasn’t finished last time.
I Want to Install GDB on Linux
Okay, I downgraded the Linux distribution running on WSL from <span>24.04</span>
to <span>22.04</span>
, and as a result, <span>gcc</span>
and <span>gdb</span>
were all installed successfully.
sudo apt install gcc
sudo apt install gdb
This indicates that it was indeed a problem with
<span>24.04</span>
, but I am not quite sure why. It might be because <span>22.04</span>
installs <span>gcc11</span>
by default, while <span>24.04</span>
installs <span>gcc14</span>
by default. So if you have similar issues, you can try downgrading.
Printing/Tracking Variables
We set a breakpoint at line 21 of the function:
Thread 1 hit Breakpoint 1, main () at testOP.cpp:21
21 S s2{1};
At this point, run and use <span>p variable_name</span>
to print the variable’s name.
(gdb) p s2
$1 = {num = 8}
Since <span>s2</span>
has not been assigned a value yet, what is printed is the residual data in memory. After running one more line, <span>s2</span>
will have a value:
(gdb) n
22 cout << (s1 == s2) << endl;
(gdb) p s2
$7 = {num = 1}
Using <span>display variable_name</span>
can track the variable, and its value will be printed every time an operation is executed:
(gdb) b 21
Breakpoint 3 at 0x7ff619ac146e: file testOP.cpp, line 21.
(gdb) r
Starting program: D:\Codes\leetcode\3133\test.exe
[New Thread 4288.0x2c34]
[New Thread 4288.0x67ec]
[New Thread 4288.0x3718]
Thread 1 hit Breakpoint 3, main () at testOP.cpp:21
21 S s2{1};
(gdb) display s1
1: s1 = {num = 1}
(gdb) n
22 cout << (s1 == s2) << endl;
1: s1 = {num = 1}
It is important to note that the <span>display</span>
operation needs to be executed while the program is running; otherwise, it will not find the symbol:<span>No symbol "s1" in current context.</span>
<span>undisplay variable_number</span>
can cancel tracking, for example, the number for the above <span>s1</span>
is 1 (the number before it).
(gdb) n
22 cout << (s1 == s2) << endl;
1: s1 = {num = 1}
(gdb) undisplay 1
(gdb) n
1
23 }
Printing Function Stack
<span>bt</span>
can print the function stack.
(gdb) bt
#0 main () at testOP.cpp:21
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) n
Program not restarted.
(gdb) s
S::S (this=0x5ffec8, num=1) at testOP.cpp:8
8 S(int num) : num(num) {};
(gdb) bt
#0 S::S (this=0x5ffec8, num=1) at testOP.cpp:8
#1 0x00007ff619ac147f in main () at testOP.cpp:21
For example, after entering the constructor of <span>S</span>
, this function replaces the main function as the new stack top.
Assignment
You can use <span>set var variable_name=value</span>
to assign a value to a variable.
(gdb) display s1
2: s1 = {num = 1}
(gdb) set var s1=2
(gdb) n
22 cout << (s1 == s2) << endl;
2: s1 = {num = 2}
Generally speaking, this assignment needs to follow C++ syntax, such as:
-
Ensure the variable can be assigned; it cannot be const and cannot be invisible in the current scope — for example, if GDB hasn’t run into the function yet, it can’t assign a value to a local variable inside the function, etc. -
Cannot assign a total value to a structure with multiple members, but you can use curly braces according to C++ syntax.
In summary, assignment operations that cannot be performed in code cannot be performed with <span>set var</span>
either.
Enable/Disable Breakpoints
<span>disable b</span>
makes all breakpoints ineffective.
(gdb) info b
Num Type Disp Enb Address What
3 breakpoint keep y 0x00007ff619ac146e in main() at testOP.cpp:21
breakpoint already hit 1 time
4 breakpoint keep y 0x00007ff619ac145d in main() at testOP.cpp:20
(gdb) disable b
(gdb) info b
Num Type Disp Enb Address What
3 breakpoint keep n 0x00007ff619ac146e in main() at testOP.cpp:21
breakpoint already hit 1 time
4 breakpoint keep n 0x00007ff619ac145d in main() at testOP.cpp:20
<span>enable b</span>
makes all breakpoints effective.
(gdb) enable b
(gdb) info b
Num Type Disp Enb Address What
3 breakpoint keep y 0x00007ff619ac146e in main() at testOP.cpp:21
breakpoint already hit 1 time
4 breakpoint keep y 0x00007ff619ac145d in main() at testOP.cpp:20
<span>disable b number</span>
makes a breakpoint ineffective.<span>enable b number</span>
makes a breakpoint effective.
Jump to Specific Line Number
<span>until line_number</span>
jumps to the specified location, executing the code in the interval.
(gdb) b 20
Breakpoint 5 at 0x7ff619ac145d: file testOP.cpp, line 20.
(gdb) r
Starting program: D:\Codes\leetcode\3133\test.exe
[New Thread 25504.0x5ab0]
[New Thread 25504.0x559c]
[New Thread 25504.0x550c]
Thread 1 hit Breakpoint 5, main () at testOP.cpp:20
20 S s1{1};
2: s1 = {num = 0}
(gdb) until 22
main () at testOP.cpp:22
22 cout << (s1 == s2) << endl;
2: s1 = {num = 1}
This directly executes to line 22 of the code.
Finish Function
<span>finish</span>
executes until the current function returns.
(gdb) r
Starting program: D:\Codes\leetcode\3133\test.exe
[New Thread 17196.0x1850]
[New Thread 17196.0x2fbc]
[New Thread 17196.0x3ab0]
Thread 1 hit Breakpoint 5, main () at testOP.cpp:20
20 S s1{1};
2: s1 = {num = 0}
(gdb) s
S::S (this=0x5ffecc, num=1) at testOP.cpp:8
8 S(int num) : num(num) {};
(gdb) finish
Run till exit from #0 S::S (this=0x5ffecc, num=1) at testOP.cpp:8
main () at testOP.cpp:21
21 S s2{1};
2: s1 = {num = 1}
Using <span>step</span>
to step into the constructor, and <span>finish</span>
to jump out of the function.
Jump to Next Breakpoint
<span>c</span>
runs directly from one breakpoint to the next.
(gdb) r
Starting program: D:\Codes\leetcode\3133\test.exe
[New Thread 2180.0x227c]
[New Thread 2180.0x55c4]
[New Thread 2180.0x6080]
Thread 1 hit Breakpoint 5, main () at testOP.cpp:20
20 S s1{1};
2: s1 = {num = 0}
(gdb) c
Continuing.
Thread 1 hit Breakpoint 6, main () at testOP.cpp:21
21 S s2{1};
2: s1 = {num = 1}
GDB hits the first breakpoint at line 20, and then we jump directly to line 21 where the next breakpoint is.