转载自这里,写得很好,保护作者版权
简单来说,GDB
就是 Linux
(或者说 *nix
?)环境下最通用的调试工具,它是非图形化的,人机通过“键入”各种指令直接交互,省去了鼠标点来点去之繁琐,并且在一定程度上据说也可以实现自动化调试。
按官方的说法,GDB
可以让你在另一个程序运行的时候看到程序内部发生的变化,或者看到程序崩溃时的当前操作。更具体地,GDB
主要可以做 4 件事:
- 启动程序,并指定任意运行条件
- 在给定条件下停止程序执行
- 在程序停止时,检查已经发生了什么
- 改变程序,“越过”一个 bug 去寻找更多 bug
不过知道这些其实没什么用处,GDB 归根结底是拿来用的,将之应用于实际才是硬道理。作为一个已经学习计算机科学半个多时代的“人才”,鄙人接触 Linux 也已经有几个年头,对 GDB 的大名岂知是“早有耳闻”,简直是“如雷贯耳”并且“久仰久仰”。可惜此前从未用过,每次别人说“你用 GDB 跟踪一下”的时候,鄙人总是搪塞过去,转而默默地用“printf”。所幸,最近终于大脑开窍,主动了解、学习起了 GDB,不得不说其简洁易上手,好用得紧。而这篇,就算是我对 GDB 基本用法的一个总结。
加了调试选项才能正确地显示函数、变量和代码等信息,选项很简单,就一个 -g
。
在最一般的情况下,比如调试 a.out
,只需要gdb a.out
即可。其他用法还包括指定 core dump
后的 dump
文件和调试服务程序时绑定 Pid
。
退出的命令是 quit
,快捷键 Ctrl+d
。
在交互中,直接回车代表输入和上一条一样的命令,这在单步调试时比较有用。另外支持用 TAB
键自动补全。
查看代码用 list
,简写为 `l。
(gdb) l
(gdb) l <linenum> #默认输出行号附近 10 行代码
设置断点用 break
,简写为 b
。基本用法有:
(gdb) b <linenum> # 在某行设置断点
(gdb) b <funcname> # 在某一函数处设置断点
(gdb) info b # 查看当前断点
设置断点后,还可以维护这些断点,比如删除、disable
以及激活等。其实维护的可能不仅仅是代码中的断点,还可能有观察点等,统称为停止点。
(gdb) delete# 删除所有断点
(gdb) delete <pointnum> # 删除某一断点
(gdb) disable # disable 所有断点,简写 dis
(gdb) dis <pointnum> # disable 某一断点
(gdb) enable # enable 所有断点,简写 en
(gdb) en <pointnum># enable 某一断点
(gdb) r # 即 run,从开始运行
(gdb) c # continue,继续运行到某一停止点
(gdb) n # next,单步调试,不会进入函数
(gdb) s # step,单步调试,会进入函数内部
(gdb) p i# print,打印变量或静态数组 i
(gdb) p *array@len # 打印动态数组 array,指定长度 len
(gdb) bt# backtrace,查看栈信息,即函数调用信息
(gdb) u# until,执行到当前循环退出
(gdb) finish # 执行到当前函数退出
可以用 display
命令设置自动显示的变量,当程序停止或单步跟踪时变量会自动打印。具体用法有:
(gdb) display <expr>
(gdb) display/<fmt> <expr>
(gdb) display/<fmt> <addr># addr 代表内存地址
(gdb) undisplay <dnums...># 删除自动显示
(gdb) delete display <dnums...> # 删除自动显示
(gdb) disable display <dnums...> # 使某个自动显示失效
(gdb) enable display <dnums...># 激活被失效的自动显示
(gdb) info display # 查看 display 信息
就像 printf
中的格式控制一样,gdb
可以按照不同格式打印值,具体有:
x按十六进制格式显示变量。
d按十进制格式显示变量。
u按十六进制格式显示无符号整型。
o按八进制格式显示变量。
t按二进制格式显示变量。
a按十六进制格式显示变量。
c按字符格式显示变量。
f按浮点数格式显示变量。
比如:
(gdb) p i
$2 = 101
(gdb) p/a i
$3 = 0x65
(gdb) p/x i
$4 = 0x65
(gdb) p/t i
$5 = 1100101
(gdb) p/c i
$6 = 101 'e'
(gdb) p/f i
$7 = 1.41531145e-43
使用 examine
命令查看内存,简写为 x
,其提供 3 个可选选项:n
、f
、u
。
x/<n/f/u> <addr>
n显示几个单位的地址内容
f显示的格式
u从当前地址请求的字节数,默认 4B。
b - 单字节,h - 双字节,
w - 4字节, g - 8字节
例如,x /3uh 0x8170
表示,从地址 0x8170
处读取内存,以双字节为单位,读取 3 个单位并以 16 进制显示。