连接 Linux 服务器的时候,一般无法直接使用 IDE 工具来帮助我们调试代码,只好求助于 GDB 了。GDB 调试并不难,也不比 IDE 调试复杂多少,唯一要做的只不过是多记住一些调试命令而已。
以 C 代码为例。假设我们编写了一个源文件 test.c
,那么,要使用 GDB 调试,首先要把源代码编译成可执行文件。当然,调试信息肯定是要打开的,打开方式一般就是在 gcc
命令中使用 -g
参数。例如:
$ gcc test.c -o test.out -g
有了编译后的可执行文件 test.out
后,就可以让 GDB 程序运行可执行文件进行调试了:
$ gdb test.out
GDB 的命令虽多,但结合我们使用 IDE 的经验,一般需要用到的命令也就那么几个。本文就罗列出常用的一些调试命令,供大家查询使用。
命令 | 简写 | 用法举例 | 说明 |
---|---|---|---|
file |
(gdb) file sample |
加载被调试的可执行文件。 由于 GDB 一般都在被调试程序所在目录下执行,因此文本名一般不需要带路径。 |
|
list |
l |
(gdb) list (gdb) l (gdb) l 10 (gdb) l main (gdb) l test.c:0 |
显示代码。 参数如果是行号,则显示以该行号为中心前后 10 行的代码; 如果是函数名,则显示该函数名前后 10 行代码。 参数也可以是“文件 + 行号”或“文件 + 函数”的形式。 |
layout |
(gdb) layout src (gdb) layout asm (gdb) layout regs (gdb) layout split |
显示窗口。src 源代码窗口;asm 反汇编窗口;regs 源代码 / 反汇编和 CPU 寄存器窗口;split 源代码和反汇编窗口。 |
|
break |
b |
(gdb) break main (gdb) b main (gdb) b 12 (gdb) b test.c:main (gdb) b test.c:11 |
设置断点。 参数有如下几种形式: 函数名 行号 文件名:函数名 文件名:行号 |
tbreak |
tb |
(gdb) tbreak main (gdb) tb main (gdb) tb 12 (gdb) tb test.c:main (gdb) tb test.c:11 |
设置临时断点。 参数和 break 一样。 |
info |
i |
(gdb) info (gdb) info break (gdb) i program |
查看信息。可通过(gdb) help info 显示所有可查看的信息。 |
clear |
(gdb) clear main (gdb) clear 13 (gdb) clear test.c:main (gdb) clear test.c:11 |
清除断点。 参数和 break 一样。 |
|
delete |
d |
(gdb) delete 1 (gdb) d 2 |
删除第 n 个断点。 参数是断点编号,而不是行号或者函数名。断点编号可通过如下命令查看: (gdb) i b |
disable |
(gdb) disable 1 |
暂停第 n 个断点。 参数和 delete 一样。 |
|
enable |
(gdb) enable 1 |
开启第 n 个断点。 参数和 disable 一样。 |
|
run |
r |
(gdb) run (gdb) r |
执行程序。遇到断点就会停在断点处。 |
step |
s |
(gdb) step (gdb) s |
执行到所在行若有遇到函数则进入函数,否则单步执行。 |
stepi |
si |
(gdb) stepi (gdb) si |
针对汇编,执行到所在行若有遇到函数则进入函数,否则单步执行。 |
next |
n |
(gdb) next (gdb) n |
单步执行。 |
nexti |
ni |
(gdb) nexti (gdb) ni |
针对汇编的单步执行。 |
continue |
c |
(gdb) continue (gdb) c |
从断点处继续执行。 |
print |
p |
(gdb) print a (gdb) p foo(3) (gdb) p a+1 |
打印值。 可以是变量、表达式、函数调用等的返回值。 |
backtrace |
bt |
(gdb) backtrace (gdb) bt |
显示调用的堆栈信息。 |
thread |
(gdb) thread 1 |
切换线程。 参数是线程号,可通过如下命令查看线程号: (gdb) info threads |
|
watch |
(gdb) watch a |
监视表达式的值是否改变。 | |
finish |
(gdb) finish |
运行程序,直到当前函数完成返回。 返回时会打印函数的堆栈地址、返回值、参数值等信息。 |
|
frame |
(gdb) frame 0 |
移动到指定的栈帧,并打印栈的信息。 参数是帧编号,如果不指定,则打印当前栈的信息。 |
|
display |
(gdb) display b |
程序每次在断点处暂停时,打印出给定表达式的值。 | |
undisplay |
(gdb) undisplay 1 |
取消先前的 display 设置,编号从 1 开始递增。 |
|
set args |
(gdb) set args 127.0.0.1 8080 |
设置程序参数。 | |
show args |
(gdb) show args |
显示已经设置的程序参数。 | |
call |
(gdb) call add(3, 4) |
调用函数,并传递参数。 | |
kill |
k |
(gdb) kill (gdb) k |
强行终止当前正在调试的程序。 |
quit |
q |
(gdb) quit (gdb) q |
退出 GDB。 |
除了上面的命令,一些快捷操作也值得注意。
- 回车键可以重复上一条命令,这样在大量执行
next
或step
等命令时,显得特别方便。 CTRL-A CTRL-X
可以打开或者关闭tui
模式(即 Text User Interface,是一个可视化的用户窗口,一般结合layout
使用)。CTRL-L
用于刷新窗口。当窗口混乱到不可视的时候就可以用这个命令来刷新。- 打开
tui
模式后,可通过上下左右方向键移动上方源码的窗口;通过CTRL-B
,CTRL-F
,CTRL-N
,CTRL-P
,在下方命令窗口移动光标或者查看前后历史记录。