【C++】使用gdb在命令行下调试C++程序(二)

如果你没看过上篇文章,建议你看看上篇【C++】使用gdb在命令行下调试C++程序(一)

这篇文章补充上次没写完的gdb调试。

我就是要在Linux上安装gdb

好的,我将WSL搭载的Linux发行版从24.04降级到22.04,结果gcc gdb全部安装成功了。

sudo apt install gcc
sudo apt install gdb

这说明真的就是24.04的问题,但是为什么我也不太清楚,可能因为22.04默认安装gcc11,而24.04默认安装gcc14。所以如果你也有类似的问题,可以尝试降级。

打印/追踪变量

我们在函数的21行打一个断点:

css 复制代码
Thread 1 hit Breakpoint 1, main () at testOP.cpp:21
21          S s2{1};

此时运行,使用p 变量名来打印变量的名字

ini 复制代码
(gdb) p s2
$1 = {num = 8}

由于s2还没被赋值,此时打印的是内存的残留数据,再运行一行,s2的值就有了:

ini 复制代码
(gdb) n
22          cout << (s1 == s2) << endl;
(gdb) p s2
$7 = {num = 1}

使用display 变量名可以追踪变量,每次执行操作时都会打出变量的值:

ini 复制代码
(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}

需要注意的是display操作需要在程序运行时执行,否则会找不到符号:No symbol "s1" in current context.

undisplay 变量编号,可以取消跟踪,比如上面的s1编号就是1(前面那个数字)

ini 复制代码
(gdb) n
22          cout << (s1 == s2) << endl;
1: s1 = {num = 1}
(gdb) undisplay 1
(gdb) n
1
23      }

打印函数堆栈

bt可以打印函数的堆栈

dart 复制代码
(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

比如我在进入S的构造函数以后,此函数就取代了main函数成为新的栈顶。

赋值

可以使用set var 变量名=值对变量进行赋值

ini 复制代码
(gdb) display s1
2: s1 = {num = 1}
(gdb) set var s1=2
(gdb) n
22          cout << (s1 == s2) << endl;
2: s1 = {num = 2}

大体上来说这种赋值需要遵循C++的语法,比如

  1. 需要保证变量是可以赋值的,不能为const,不能在当前作用域不可见------比如gdb还没运行到函数内部,就对函数内的局部变量赋值,等等。
  2. 不能对有多个成员的结构体赋总值,但是可以按C++语法用大括号。

总之,代码里不能进行的赋值操作,set var也不行。

开启 / 禁用断点

disable b使所有断点无效

less 复制代码
(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

enable b 使所有断点有效

less 复制代码
(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

disable b 编号使一个断点无效 enable b 编号使一个断点有效

指定行号跳转

until 行号 进行指定位置跳转,执行完区间代码

ini 复制代码
(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}

这里直接一路执行到代码的22行

结束函数

finish 在一个函数内部,执行到当前函数返回

ini 复制代码
(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}

使用step步进到构造函数中,finish直接跳出函数。

跳转到下一个断点

c 从一个断点处,直接运行至下一个断点处

ini 复制代码
(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在20行命中第一个断点,然后我们直接跳到21行下一个断点。

本文使用 markdown.com.cn 排版

相关推荐
egoist20231 小时前
【C++指南】一文总结C++类和对象【下】
c++·编辑器·类和对象·初始化列表·友元·匿名对象·c++ 11
SNAKEpc121386 小时前
Qt开源控件库(qt-material-widgets)的编译及使用
c++·qt·开源
轩宇^_^8 小时前
C++ 类与对象的实际应用案例详解
开发语言·c++
c7_ln8 小时前
编程视界:C++命名空间
开发语言·c++·笔记
十五年专注C++开发9 小时前
SQLiteStudio:一款免费开源跨平台的SQLite管理工具
数据库·c++·qt·sqlite
Serendipity-Solitude9 小时前
c++中的数学函数库(少)
开发语言·c++
坚定学代码9 小时前
PIMPL模式
c++
imgsq9 小时前
已安装 MFC 仍提示“此项目需要 MFC 库”的解决方法 (MSB8041)
c++·mfc
香菇滑稽之谈10 小时前
责任链模式的C++实现示例
开发语言·c++·设计模式·责任链模式