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

去年我有个同事在命令行下非常帅气地调试C++程序,确实羡慕到我了,我就计划写篇文章介绍用gdb在命令行下调试,结果一拖就拖了很久,这次还是不能再拖了。

在Ubuntu(WSL)下安装gcc和gdb

都用命令行了,那肯定先在wsl上试试啊,毕竟一句话的事:

sudo apt install gcc

然后就没有然后了,gcc的安装始终在报错:

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 libasan8 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 libatomic1 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 libcc1-0 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 libhwasan0 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 libitm1 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 liblsan0 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 libquadmath0 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 libtsan2 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
 libubsan1 : Depends: gcc-14-base (= 14.2.0-4ubuntu2~24.04) but 14.2.0-4ubuntu2 is to be installed
E: Unable to correct problems, you have held broken packages.

我的系统是 WSL2 下的 Ubuntu 24.04,软件源被我替换成了清华的tuna源,我尝试过很多办法解决这个问题,包括:
安装其他版本的gcc:

sudo apt install gcc-13

gcc-13在当前软件源是可用的,通过以下命令可以查询到:

apt-cache policy gcc-13
gcc-13:
  Installed: (none)
  Candidate: 13.3.0-6ubuntu2~24.04
  Version table:
     13.3.0-6ubuntu2~24.04 500
        500 https://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-updates/main amd64 Packages
        500 https://mirrors.tuna.tsinghua.edu.cn/ubuntu noble-security/main amd64 Packages
        500 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
        500 http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages
     13.2.0-23ubuntu4 500
        500 https://mirrors.tuna.tsinghua.edu.cn/ubuntu noble/main amd64 Packages
        500 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages

或者一些常规的办法,比如更新所有本地的软件:

sudo apt upgrade

执行清理和自动清理:

sudo apt clean
sudo apt autoclean

修复依赖:

sudo apt --fix-broken install
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
0 upgraded, 0 newly installed, 0 to remove and 180 not upgraded.

反正这个问题在我文章写完的时候还没解决,我就先在Windows上搞这个了。gnu的原教旨主义者这时候估计就摩拳擦掌准备从源代码构建了,但我比较懒,我觉得Windows安装会更方便一点。

在Windows上安装gcc和gdb

准确来说我安装的是MingW-w64,gcc这一套东西都是Linux特有的,Windows的使用仅仅是模拟Linux。

我电脑在2023年装机的时候装过一次gcc,是从这个网站下载的:https://files.1f0.de/mingw/

我都不记得当时看哪个教程下载的,压缩包里没有gdb,如果我坚持用这个版本的gcc就只能从源代码编译了。考虑到我电脑上没什么C++大项目,我直接重新装一个。

MingW-w64的官网包含一些预构建的工具链,不必非得在自己电脑构建一遍:
https://www.mingw-w64.org/downloads/#mingw-w64-builds
我用的是这个
直接在github下压缩包即可,官方的安装器都不需要下(虽然那个安装器也不过是把选好的压缩包下载到本地解压了,环境变量都要自己搞)
https://github.com/niXman/mingw-builds-binaries/releases

上面链接你可能打不开,可以找我要压缩包。

反正一通折腾总算安装完了:
这个打印就说明你安装成功了

使用gdb在命令行下调试C++程序

以我之前写的一个测试双等于号的程序为例子:

#include <iostream>

using namespace std;

struct S
{
public:
    S(int num) : num(num) {};
    bool operator==(S s)
    {
        return this->num == s.num;
    }

private:
    int num;
};

int main()
{
    S s1{1};
    S s2{1};
    cout << (s1 == s2) << endl;
}

执行以下命令,在debug模式下编译C++程序:

g++ -g -o test testOP.cpp

使用gdb debug程序:

gdb .\test.exe

如果你的终端在gdb输入命令时,无法使用backspace键删除(尤其是使用VS Code自带的终端),可能是终端没有解锁编辑模式,使用以下命令解锁即可:

set editing off

查看代码

l 行号显示从此行开始的10行代码

(gdb) l 1
1       #include <iostream>
2
3       using namespace std;
4
5       struct S
6       {
7       public:
8           S(int num) : num(num) {};
9           bool operator==(S s)
10          {

这里输入l 0也是一样的效果。l是list的缩写,gdb有很多将单个单词缩写成一个字母的用法,如果你无法确定,放心大胆地用,当缩写有歧义时,gdb会询问你。

比如这里我输入d b,gdb就不知道我的b指的是什么。

(gdb) d b
Ambiguous delete command "b": bookmark, breakpoints.

gdb会自动记忆命令,并在你不进行任何输入而直接按下回车时重复命令,某些情况下,会智能对命令进行修改。比如这里,只要你一直敲击回车,gdb就会不断更新list命令的参数,打出完整的代码:

(gdb) l 1
1       #include <iostream>
2
3       using namespace std;
4
5       struct S
6       {
7       public:
8           S(int num) : num(num) {};
9           bool operator==(S s)
10          {
(gdb)
11              return this->num == s.num;
12          }
13
14      private:
15          int num;
16      };
17
18      int main()
19      {
20          S s1{1};
(gdb)
21          S s2{1};
22          cout << (s1 == s2) << endl;
23      }
(gdb)
End of the file was already reached, use "list ." to list the current location again

断点

b 行号在那一行打断点,b是breakpoint的缩写

(gdb) b 20
Breakpoint 2 at 0x7ff70ac6145d: file testOP.cpp, line 20.

b 源文件:函数名 在该函数的第一行打上断点

(gdb) b testOP.cpp:operator==
Breakpoint 3 at 0x7ff70ac62a3b: file testOP.cpp, line 11.

info b 查看断点的信息

(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x00007ff70ac6145d in main() at testOP.cpp:20     
3       breakpoint     keep y   0x00007ff70ac62a3b in S::operator==(S) at testOP.cpp:11

d 当前要删除断点的编号 删除一个断点,d是delete的缩写

(gdb) d 2
(gdb) info b
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x00007ff70ac62a3b in S::operator==(S) at testOP.cpp:11

d breakpoints 删除所有的断点(breakpoints不能简写)

(gdb) d breakpoints
Delete all breakpoints? (y or n) Y
(gdb) info b       
No breakpoints or watchpoints.

调试

r 运行程序直到第一个断点,r是run的缩写

(gdb) b 21
Breakpoint 4 at 0x7ff70ac6146e: file testOP.cpp, line 21.
(gdb) r
Starting program: D:\Codes\leetcode\3133\test.exe 
[New Thread 27792.0x40c0]
[New Thread 27792.0x6c60]
[New Thread 27792.0x2d54]

Thread 1 hit Breakpoint 4, main () at testOP.cpp:21
21          S s2{1};

n逐行运行,不进入函数(进栈),n是next的缩写

(gdb) r
Starting program: D:\Codes\leetcode\3133\test.exe 
[New Thread 5928.0x2170]
[New Thread 5928.0x6c68]
[New Thread 5928.0x6a3c]

Thread 1 hit Breakpoint 4, main () at testOP.cpp:21
21          S s2{1};
(gdb)
(gdb) n
22          cout << (s1 == s2) << endl;
(gdb)
1
23      }
(gdb)
0x00007ff70ac612ef in __tmainCRTStartup ()
(gdb)
Single stepping until exit from function __tmainCRTStartup,
which has no line number information.
[Thread 5928.0x2170 exited with code 0]
[Thread 5928.0x6c68 exited with code 0]
[Thread 5928.0x6a3c exited with code 0]
[Inferior 1 (process 5928) exited normally]

s 逐语句运行,会进入函数,s是step的缩写

(gdb) s
S::S (this=0x5ffec8, num=1) at testOP.cpp:8
8           S(int num) : num(num) {};
(gdb)
main () at testOP.cpp:22
22          cout << (s1 == s2) << endl;
(gdb)
S::operator== (this=0x5ffecc, s=...) at testOP.cpp:11
11              return this->num == s.num;
(gdb)
12          }
(gdb)
1
main () at testOP.cpp:23
23      }
(gdb)
0x00007ff70ac612ef in __tmainCRTStartup ()
(gdb)
Single stepping until exit from function __tmainCRTStartup,
which has no line number information.
[Thread 28652.0x6ed0 exited with code 0]
[Thread 28652.0x5db0 exited with code 0]
[Thread 28652.0x6eec exited with code 0]
[Inferior 1 (process 28652) exited normally]

退出gdb

exit退出gdb命令行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值