3. GDB断点详解:设置断点、条件断点、临时断点、断点管理、断点的高级用法
断点这东西,说白了就是调试的基石。没有断点,你只能眼睁睁看着程序跑飞,然后一脸懵。我刚开始用GDB那会儿,只会最简单的b main,后来踩的坑多了,才慢慢摸透断点的各种玩法。今天咱们就把断点彻底聊透。
3.1 设置断点的基本姿势
最常用的就是break命令,简写b。你可以按函数名、行号、文件名+行号来设断点。
(gdb) b main # 在main函数入口
(gdb) b 42 # 在当前文件第42行
(gdb) b foo.c:128 # 在foo.c的第128行
(gdb) b my_function # 在任意文件的my_function
我个人习惯用b file.c:line这种形式,尤其是项目大了以后,同名函数很容易撞车。你想想看,如果两个文件都有init(),不加文件名GDB会给你设两个断点,有时候自己都忘了哪个是哪个。
info files先看看当前加载了哪些源文件,再精确设断点,省得设错地方。
3.2 条件断点:只在需要时停下
条件断点是我在项目中用得最多的。比如循环里只想看第1000次迭代的情况,总不能手动按1000次c吧?
(gdb) b 42 if i == 1000
(gdb) b my_function if x > 0 && y < 0
(gdb) b file.c:200 if strcmp(name, "error") == 0
我曾经调试过一个内存泄漏问题,只在某个特定大小的分配时才会触发。用条件断点b malloc if size == 4096,一下子就定位到了问题。要是没有条件断点,你得在malloc里断住几百次,手都按酸了。
3.3 临时断点:用完即弃
临时断点用tbreak,它只生效一次。断点命中后自动删除,特别适合那种「我就想看一眼这里,然后继续跑」的场景。
(gdb) tbreak 88
(gdb) tbreak my_function
我经常在调试某个函数时,临时想看看调用栈,就在函数入口设个tbreak,然后bt看一下,再c继续。省得后面还要手动清理断点。
3.4 断点管理:别让断点失控
项目大了,断点一多就容易乱。我见过同事调试时设了20多个断点,最后自己都搞不清哪个是哪个。这时候管理命令就派上用场了。
| 命令 | 作用 |
|---|---|
info breakpoints |
列出所有断点,带编号和状态 |
disable 2 |
禁用编号2的断点(不删除) |
enable 2 |
重新启用 |
delete 2 |
删除编号2的断点 |
clear main |
删除main函数处的断点 |
我个人习惯给断点加注释,方便记忆:
(gdb) b main
(gdb) comment 1 "这是程序入口,检查初始化"
(gdb) b 200 if errno != 0
(gdb) comment 2 "检查错误处理分支"
嗯,这里要注意:comment命令在旧版GDB里可能不支持,建议用GDB 10以上版本。
3.5 断点的高级用法
玩到高级阶段,断点就不只是「停住」那么简单了。你可以让断点执行一系列命令,甚至自动打印变量然后继续跑。
3.5.1 断点命令列表
(gdb) b 42
(gdb) commands
> print x
> print y
> continue
> end
这样每次命中第42行,GDB会自动打印x和y的值,然后继续执行。我在调试一个网络协议栈时,用这个技巧在每个包处理函数入口打印包类型和长度,省得一次次手动敲命令。
3.5.2 硬件断点 vs 软件断点
GDB默认用软件断点,就是在指令里插入int 3。但有些场景必须用硬件断点:
- 调试只读内存(比如Flash里的代码)
- 调试自修改代码
- 某些嵌入式平台不支持软件断点
(gdb) hbreak 0x40001000 # 在地址处设硬件断点
(gdb) info breakpoints # 看类型列,hw表示硬件断点
3.5.3 观察点:数据变化自动断
观察点(watchpoint)是断点的变种,它监视某个变量或内存地址,一旦值发生变化就停下。
(gdb) watch my_var # 监视变量
(gdb) watch *(int*)0x7fff # 监视内存地址
(gdb) rwatch my_var # 读时断住
(gdb) awatch my_var # 读写都断
我曾经用watch抓过一个野指针问题。有个全局变量莫名其妙被改写了,我在它上面设了观察点,程序跑起来后立刻断在了一个不该写它的函数里。嗯,那感觉就像破案一样爽。
- 条件断点用
if,避免无效中断 - 临时断点
tbreak,用完即焚 - 断点管理用
info/disable/enable/delete - 高级玩法:
commands、硬件断点、观察点
最后说一句:断点不是越多越好。我见过有人设了30个断点,结果程序根本跑不动。精确定位,少而精,才是调试的真谛。
可可精品资料库