gdb 调试基础

2023-10-20 17:46:15 浏览数 (2)

程序运行过程中,会产生各种各样的错误和异常信息,这些信息我们可以通过打印日志、输出文字等方式来判断和检测问题,但有的时候程序是在运行态出现故障,使用打印日志等手段没办法精准的定位问题。如果使用gdb来调试,这种问题就可以迎刃而解了。gdb 可以完全操控程序运行,让程序走就走,让程序暂停就暂停,还可以随时查看程序运行时内部变量的值等信息。

使用 gdb 调试程序必须保证符合以下两个条件。

  1. 程序可以正常编译通过
  2. 程序编译时,必须用 -g 选项

// 加入 -g 选项时程序可以被调试 gcc main.c -o main -g

【开始调试】 要调试一个程序,你只需要输入命令 “gdb 被调试程序名” 就可以了,如 gdb main 【调试中列出源码】 当进入 gdb 调试状态后,程序会等待你输入调试的命令,此时,你可以输入 list 命令(也可以使用简写 l),列出程序的源码,来决定对哪一个逻辑进行调试。每执行一次 list 都只打印 10 行代码,可以多输入几次输出完整的信息。也可以使用 “list 函数名” 来直接跳转到某个函数上。如下:

代码语言:javascript复制
(gdb) list
1#include <stdio.h>
2#include <unistd.h>
3
4int main(int argc, char* argv[])
5{
6pid_t pid = fork();
7
8if (pid == 0)
9{
10// 新创建的子进程
(gdb) list
11while (1)
12{
13printf(“child : PID = %d, ParentID = %dn”, getpid(), getppid());
14sleep(1);
15}
16}
17else if (pid > 0)
18{
19// 当前进程
20while (1)
(gdb) list
21{
22printf(“parent: PID = %d, ParentID = %dn”, getpid(), getppid());
23sleep(1);
24}
25}
26
27return 0;
28}
【设置断点】 如果你想让程序在运行时,在第 11 行停止等待,你可以在 11 行使用 break 命令设置断点(也可以使用简拼 b 11),如下:
(gdb) break 11
Breakpoint 1 at 0x80484fb: file fork.c, line 11.

【查看断点信息】 如果你设置了多个断点,你可以使用 info break 命令查看断点,如下:

代码语言:javascript复制
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080484fb in main at fork.c:11

它显示我在 fork.c 的第 11 行设置了一个断点,编号是1、类型是断点、当前是启用状态,它的地址是什么。 【设置条件断点】 除了上面简单的断点外,也可以设定条件断点,比如我希望在第8行设定一个断点,并且当 pid == 0 的时候该断点才生效。那么可以使用 break 8 if pid = 0,添加完成后再次使用 info break 查看断点信息如下:

代码语言:javascript复制
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x080484fb in main at fork.c:11
2       breakpoint     keep y   0x080484f5 in main at fork.c:8
stop only if pid = 0

【启用/禁用某断点】 使用 info break 命令我们可以看到每一个断点的 Num 号,我们可以对这些断点进行启用和禁用,使用命令 “disable 断点编号”即可禁用某个断点,如下“

代码语言:javascript复制
(gdb) disable 1
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep n   0x080484fb in main at fork.c:11
2       breakpoint     keep y   0x080484f5 in main at fork.c:8
stop only if pid = 0

禁用后,Num 为 1 的断点 Enb 就变成了 n,相反如果想再次启用就使用 enable 【删除断点】 删除断点使用 delete 就可以。比如 delete 2,那么第2个断点就被删除了。

代码语言:javascript复制
(gdb) delete 2
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep n   0x080484fb in main at fork.c:11

【运行被调试程序】 当你已经设定好断点等信息后,可以通过命令 run 来运行程序,程序会自动在你设定的断点位置停止。

代码语言:javascript复制
(gdb) run
Starting program: /home/mycode/0629/fork 
Breakpoint 1, main (argc=1, argv=0xbffff174) at fork.c:6
6pid_t pid = fork();

【单步执行】 当卡在某断点位置时,你希望程序一步一步的向下指向,就输入 next 命令,相当于 VS 的 F10。 【单步跳入】 当程序执行到某个函数时,你希望跟踪这个函数内部的执行步骤,你可以使用 step 命令,,相当于 VS 的 F11。 【跳出】 当你希望跳出函数时,可以使用 finish 命令,相当于 VS 的 SHIFT F11 【其他更多命令】

0 人点赞