gdb调试工具详解
gdb调试详解
是 GNU 调试器(GNU Debugger)的缩写,它是一个功能强大的 Unix-like 系统下的源代码调试器。使用 gdb,程序员可以查看程序在运行时的状态,设置断点,单步执行代码,检查变量的值,以及执行其他调试任务。(在命令行终端中进行)
gdb启动流程
-
编译相关:编译链接的时候
-g表示可以调试,如果要使用gdb调试记得加上1
gcc -g test.cpp -o test
-
启动gdb,示例如下:
1
2gdb test
gbd -q test //表示不打印gbd版本信息,界面比较干净 -
gdb下查看源码:
list1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52(gdb) list
9
10
11 int main()
12 {
13 int i,fd,size1 ,size2 ,len;
14 char *buf = "helo!I'm liujiangyong ";
15 char buf_r[15];
16 len = strlen(buf);
17 fd = open("/home/hello.txt",O_CREAT | O_TRUNC | O_RDWR,0666);
18 if (fd<0)
(gdb)
19 {
20 perror("open :");
21 exit(1);
22 }
23 else
24 {
25 printf("open file:hello.txt %d\n",fd);
26 }
27 size1 = write(fd,buf,len);
28 if (fd<0)
(gdb)
29 {
30 printf("writre erro;");
31
32 }
33 else
34 {
35 printf("写入的长度:%d\n写入文本内容:%s\n",size1,buf);
36
37 }
38 lseek(fd,0,SEEK_SET);
(gdb)
39 size2 = read(fd,buf_r,12);
40 if (size2 <0)
41 {
42 printf("read erro\n");
43 }
44 else
45 {
46 printf("读取长度:%d\n 文本内容是:%s\n",size2,buf_r);
47 }
48 close(fd);
(gdb)
49
50
51 }
(gdb)
Line number 52 out of range; write.c has 51 lines.
(gdb) -
gbd下运行程序:
run该命令会运行程序直到结束或者遇到断点等待下一个命令
1
2
3
4
5
6
7
8
9
10
11
12(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/eit/c_test/test
open file:hello.txt 3
写入的长度:22
写入文本内容:helo!I'm liujiangyong
读取长度:12
文本内容是:helo!I'm liu
[Inferior 1 (process 19987) exited normally]
(gdb) -
gdb下设置断点:
break+行号该命令会在某一行设置一个断点,
info breakpoints会显示所有断点信息1
2
3
4
5
6
7
8
9
10
11
12
13(gdb) b 5
Breakpoint 3 at 0x400836: file write.c, line 5.
(gdb) b 26
Breakpoint 4 at 0x4008a6: file write.c, line 26.
(gdb) b 30
Breakpoint 5 at 0x4008c6: file write.c, line 30.
(gdb) info breakpoints
Num Type Disp Enb Address What
3 breakpoint keep y 0x0000000000400836 in main at write.c:5
4 breakpoint keep y 0x00000000004008a6 in main at write.c:26
5 breakpoint keep y 0x00000000004008c6 in main at write.c:30
(gdb)num type disp enb address what 断点编号 类型 断点执行一次后是否有效,keep(有) 当前断点是否有效,y(有) 内存地址 在函数中的位置 -
gdb下单步执行:
continue、step、next、finish-
continue:在断点处继续执行程序 -
next:执行下一行代码(跳过函数内部) -
step:执行下一行代码(进入函数内部) -
finish:执行完当前函数并返回到父函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37(gdb) r
Starting program: /home/eit/c_test/test
Breakpoint 3, main () at write.c:12
12 {
(gdb) n
14 char *buf = "helo!I'm liujiangyong ";
(gdb)
16 len = strlen(buf);
(gdb)
17 fd = open("/home/hello.txt",O_CREAT | O_TRUNC | O_RDWR,0666);
(gdb) s
open64 () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb)
main () at write.c:18
18 if (fd<0)
(gdb)
25 printf("open file:hello.txt %d\n",fd);
(gdb)
__printf (format=0x400a26 "open file:hello.txt %d\n") at printf.c:28
28 printf.c: No such file or directory.
(gdb) c
Continuing.
open file:hello.txt 3
Breakpoint 4, main () at write.c:27
27 size1 = write(fd,buf,len);
(gdb)
Continuing.
写入的长度:22
写入文本内容:helo!I'm liujiangyong
读取长度:12
文本内容是:helo!I'm liu
[Inferior 1 (process 20737) exited normally]
(gdb) -
-
gdb下查看变量:
print、whatis1
2
3
4
5
6
7
8
9
10main () at write.c:28
28 if (fd<0)
(gdb)
35 printf("写入的长度:%d\n写入文本内容:%s\n",size1,buf);
(gdb) print fd
$10 = 3
(gdb) whatis fd
type = int
(gdb) -
gdb下退出gdb:
quit1
2
3
4
5
6
7
8
9
10
11(gdb) r
Starting program: /home/eit/c_test/test
open file:hello.txt 3
写入的长度:22
写入文本内容:helo!I'm liujiangyong
读取长度:12
文本内容是:helo!I'm liu
[Inferior 1 (process 20815) exited normally]
(gdb) q
root@ubuntu:/home/eit/c_test#
常用命令
当使用表格来表示 gdb 的常用命令时,可以如下所示:
| 命令分类 | 命令 | 描述 |
|---|---|---|
| 启动和退出 | gdb your_program |
启动 GDB 并加载指定的程序 |
quit 或 q |
退出 GDB | |
| 调试控制 | run [arguments] 或 r [arguments] |
运行程序并传递参数 |
continue 或 c |
继续执行,直到遇到下一个断点或程序结束 | |
next 或 n |
执行下一行代码(不进入函数) | |
step 或 s |
执行下一行代码(进入函数) | |
finish |
执行完当前函数并返回到父函数 | |
| 断点管理 | break [location] 或 b [location] |
在指定位置设置断点 |
info breakpoints 或 info b |
显示所有断点信息 | |
disable [breakpoint_number] |
禁用指定编号的断点 | |
enable [breakpoint_number] |
启用指定编号的断点 | |
delete [breakpoint_number] 或 d [breakpoint_number] |
删除指定编号的断点 | |
| 变量和内存查看 | print [variable_name] 或 p [variable_name] |
显示变量的值 |
ptype [variable_name] |
显示变量的类型 | |
set var [variable_name]=[newValue] |
修改变量的值 | |
x/NFU [address] |
显示内存内容,N是数量,F是格式,U是单位,address是地址 | |
| 其他常用命令 | list [location] 或 l [location] |
显示源代码 |
backtrace 或 bt |
显示堆栈跟踪 | |
watch [expression] |
设置观察点,当表达式值改变时停止 | |
catch [event] |
捕获特定事件(如异常) | |
show path |
显示GDB搜索源代码的路径 | |
setargs [arguments] |
设置传递给程序的命令行参数 | |
show args |
显示设置好的运行时参数 | |
attach [process_id] |
连接到正在运行的进程 | |
detach |
断开与已连接进程的连接 | |
shell [command] |
执行shell命令 | |
| 自定义命令和脚本 | define [cmd_name] [command_list] |
定义自定义命令 |
| 脚本文件 | 使用脚本文件来自动化调试任务 | |
| 多线程和多进程调试 | info threads |
显示所有线程信息 |
thread [tid] |
切换到指定编号的线程 | |
| `set follow-fork-mode [child | parent]` |
请注意,这个表格只是提供了 gdb 的一些常用命令的概览,每个命令还有更多的选项和用法可以探索。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 龙锦!


