GDB 常用命令一览

命令

GDB 是 Linux 下的命令行调试工具。
启动 GDB 有如下几种方式:

  1. gdb <program> 直接启动执行程序

  2. gdb <program> core 用gdb 同时调试一个可执行程序和core文件。core 是程序非法执行后 core dump 产生的文件

  3. gdb <program> <PID> 指定进程, gdb会自动 attach 上去。program 应该在 PATH 环境变量中可以搜索得到。

常用的 gdb 命令如下

信息 info

info 可以简写成 i

  • info args 列出参数

  • info breakpoints info break i b 列出所有断点

  • info break number i b number 列出序号为 number 的的断点

  • info watchpoints i watchpoints 列出所在 watchpoints

  • info threads 列出所有线程

  • inifo registers 列出寄存器的值

  • info set 列出当前 gdb的所的设置

  • i frame

  • i stack

  • i locals

  • i catch

断点和监视 break & watch

break 可以简写为 b

  • break fun_name b fun_name 在 fun_name 处打断点

  • b line_number 在 line_number 处打断点

  • b +offset 在offset 行后加断点

  • b -offset 同上

  • b file_name:fun_name 文件的方法名处打断点

  • b fine_name:line_number 同上

  • b *address 在某地址处打断点。适用于没有源码的情况

  • b line_number if condition 条件断点。当条件为 true 时会中断

  • tbreak tb 单次命中断点。如 tb 12 表示只会在第12行命中一次。
    watch 可以添加监视。watch 没有简写

  • watch var 监视var变量

  • watch condition 带条件的监视。如 watch a>1

删除和禁用断点

  • clear 清除当前行的断点

  • clear fun_name 清除 fun_name 中的所有断点

  • clear line_number 删除该行的断点

  • delete 简写 d . 删除所有的 breakpoints, watchpoints, or catchpoints.

  • d num 删除序号为 num 的断点

  • d num1-num2 删除序号从 num1 到 num2 的所有断点

  • disable/enable num 禁用/启用序号为 num 的断点

  • disable/enable num1-num2 禁用/启用 序号从 num1到 num2 的断点

调试

  • run 简写 r 运行程序

  • step 简写 s 单步,可以进入方法(相当于 VS 的 F11)

  • finish 跳出当前方法(相当于VS 的 sh+F11)

  • next 简写 n 单步,不会进入方法(相当于 VS 的 F10)

  • until line-number 运行到 line-number 行。line-number 只能比当前行数大。 until 还可以接 function name, address, filename:function or filename:line-number

  • where 显示当前行数和方法

  • backtrace 简写 bt 显示当前的栈信息

  • bt full 打印完整的栈信息

  • frame 简写 f 显示当前栈的 frame 信息

  • f number 选择frame

  • up / down / up number /down number 选择 frame

源码

  • list 简写 l 列出源码

  • l num 列出 num 行前后的源码

  • l fun 列出方法 fun 的源码

  • l start_num, end_num

  • l file_name:fun_name

  • set listsize count 设置一次显示多少行源码(默认为10)

  • show listsize 显示listsize

  • directiory dir_name 简写 dir dir_name , 将指定的目录加入源码文件的前缀

  • show dir

  • i line 显示 l 所指的行(注意不是当前行)在obj中的起始地址

  • i line line_number 同上

  • stepi si 汇编级调试

  • nexti ni

变量

  • print var 简写 p var 打印变量var

  • p file_name:var

  • p/x var 以16进制打印整型变量 。

  • p/d var 10进制

  • p/u var unsigned int

  • p/o var 8进制

  • p/t var 2进制 (1byte/8bits)

  • p/c var 以字符形式

  • p/f var 以 floating 形式

  • p/a var 以十六进制地址

  • x/4b &var 以 4 byte 打印var 的内存

  • ptype var 显示var 的类型

  • ptype date-type 显示原类型

启动

  • run 简写 r

  • continue 简写 c

  • kill 杀掉当前调试的程序

  • quit 简写 q 退出gdb

实践

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

int fun_add(int a,int b){
int s = a+b;
return s;
}

int main(){
int a = 0;
cout<<a<<endl;
cout<<a++<<endl;
cout<<++a<<endl;

int x = fun_add(a, 2);
cout<<x<<endl;

while(a < 10){
a++;
}

return 0;
}

编译:
> g++ -g ./test.c -o test

调试:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
zr@zr:~/code/use_gdb/src1$ gdb ./test <----- 启动调试
GNU gdb (Ubuntu 8.1-0ubuntu3.1) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test...done.
(gdb) l <----- 列出源码
1 #include <iostream>
2
3 using namespace std;
4
5 int fun_add(int a,int b){
6 int s = a+b;
7 return s;
8 }
9
10 int main(){
(gdb) <----- 回车,进行上一次操作
11 int a = 0;
12 cout<<a<<endl;
13 cout<<a++<<endl;
14 cout<<++a<<endl;
15
16 int x = fun_add(a, 2);
17 cout<<x<<endl;
18
19 while(a < 10){
20 a++;
(gdb) b 12 <----- 第12行打断点
Breakpoint 1 at 0x8b3: file ./test.c, line 12.
(gdb) b 16 <----- 第16行打断点
Breakpoint 2 at 0x92f: file ./test.c, line 16.
(gdb) l fun_add <----- 查看 fun_add 所在的行
1 #include <iostream>
2
3 using namespace std;
4
5 int fun_add(int a,int b){
6 int s = a+b;
7 return s;
8 }
9
10 int main(){
(gdb) b fun_add <----- 方法 fun_add 打断点
Breakpoint 3 at 0x894: file ./test.c, line 6.
(gdb) r <----- 启动程序。将在第一个断点外中断
Starting program: /home/zr/code/use_gdb/src1/test

Breakpoint 1, main () at ./test.c:12
12 cout<<a<<endl;
(gdb) p a <----- 打印变量 a
$1 = 0
(gdb) n <----- 执行下一行
0
13 cout<<a++<<endl;
(gdb) p a
$2 = 0
(gdb) n
0
14 cout<<++a<<endl;
(gdb) p a
$3 = 1
(gdb) watch a <----- 监视变量 a
Hardware watchpoint 4: a
(gdb) n

Hardware watchpoint 4: a

Old value = 1
New value = 2
0x0000555555554909 in main () at ./test.c:14
14 cout<<++a<<endl;
(gdb) i b <----- 查看所有断点
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555548b3 in main() at ./test.c:12
breakpoint already hit 1 time
2 breakpoint keep y 0x000055555555492f in main() at ./test.c:16
3 breakpoint keep y 0x0000555555554894 in fun_add(int, int) at ./test.c:6
4 hw watchpoint keep y a
breakpoint already hit 1 time
(gdb) watch a>5 <----- 添加条件监视
Hardware watchpoint 5: a>5
(gdb) i b <----- 查看所有断点
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555548b3 in main() at ./test.c:12
breakpoint already hit 1 time
2 breakpoint keep y 0x000055555555492f in main() at ./test.c:16
3 breakpoint keep y 0x0000555555554894 in fun_add(int, int) at ./test.c:6
4 hw watchpoint keep y a
breakpoint already hit 1 time
5 hw watchpoint keep y a>5
(gdb) c <----- continue
Continuing.
2

Breakpoint 2, main () at ./test.c:16
16 int x = fun_add(a, 2);
(gdb) i args <----- 命中断点后查看所有参数
No arguments.
(gdb) n

Breakpoint 3, fun_add (a=2, b=2) at ./test.c:6
6 int s = a+b;
(gdb) i args <----- 查看所有参数
a = 2
b = 2
(gdb) p/t a <----- 以二进制查看变量a
$4 = 10
(gdb) finish <----- 跳出当前方法
Run till exit from #0 fun_add (a=2, b=2) at ./test.c:6
0x000055555555493e in main () at ./test.c:16
16 int x = fun_add(a, 2);
Value returned is $5 = 4
(gdb) where
#0 0x000055555555493e in main () at ./test.c:16
(gdb) n
17 cout<<x<<endl;
(gdb) c <----- continue 直到命中断点或监视的变量有了变化
Continuing.
4

Hardware watchpoint 4: a

Old value = 2
New value = 3
main () at ./test.c:19
19 while(a < 10){
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555548b3 in main() at ./test.c:12
breakpoint already hit 1 time
2 breakpoint keep y 0x000055555555492f in main() at ./test.c:16
breakpoint already hit 1 time
3 breakpoint keep y 0x0000555555554894 in fun_add(int, int) at ./test.c:6
breakpoint already hit 1 time
4 hw watchpoint keep y a
breakpoint already hit 2 times
5 hw watchpoint keep y a>5
(gdb) c
Continuing.

Hardware watchpoint 4: a

Old value = 4
New value = 5
main () at ./test.c:19
19 while(a < 10){
(gdb) c
Continuing.

Hardware watchpoint 4: a

Old value = 6
New value = 7
main () at ./test.c:19
19 while(a < 10){
(gdb) disable 4 <----- 取消断点/监视 4
(gdb) c
Continuing.