GDB 进阶指南(watch、commands等命令使用)
GDB 进阶指南
本文面向有基本调试经验的开发者,深入介绍 GDB 的一些高阶用法,尤其适用于单元测试 (UT) 场景中的变量追踪、观察点自动化命令、内存访问监控等。
1. 使用 watch 观察变量变化
watch 会在某变量值发生变化时中断程序。
示例代码
// demo_watch.c
#include <stdio.h>
int global_counter = 0;
int main() {
for (int i = 0; i < 5; ++i) {
global_counter += i;
}
return 0;
}
GDB 操作
(gdb) gcc -g demo_watch.c -o demo_watch
(gdb) gdb ./demo_watch
(gdb) break main
(gdb) run
(gdb) watch global_counter
(gdb) continue
每次 global_counter 变化,GDB 都会中断程序。
2. 给 watch 添加自动执行命令:commands
使用 commands 可以在变量变化时自动打印信息、继续执行等。
示例
(gdb) watch global_counter
(gdb) commands
> silent
> printf "global_counter changed: %d\n", global_counter
> continue
> end
这段命令让程序在变量变化时自动打印并继续执行,不手动介入。
3. 打印变量变化时的代码位置
可以结合 frame 和 info line 输出调用栈和源码位置信息。
(gdb) commands
> silent
> printf "global_counter changed to: %d\n", global_counter
> frame
> info line
> continue
> end
输出示例:
global_counter changed to: 1
#0 main () at demo_watch.c:8
Line 8 of "demo_watch.c" starts at 0x... and ends at 0x...
4. 修改已有观察点的 commands
查看观察点编号
(gdb) info breakpoints
修改指定观察点的 commands
(gdb) commands 2
> silent
> printf "Updated print: %d\n", global_counter
> continue
> end
删除 commands
(gdb) commands 2
> end
5. 监控内存地址访问:awatch / rwatch
示例代码
// demo_addr.c
int val = 42;
int main() {
int *ptr = &val;
*ptr = 100;
return 0;
}
GDB 监控地址
(gdb) break main
(gdb) run
(gdb) awatch *(int*)(&val)
(gdb) commands
> silent
> printf "val was accessed!\n"
> frame
> info line
> continue
> end
当 val 被读写时,会自动打印当前代码位置。
6. 观察结构体成员 / 复杂表达式
GDB 支持观察结构体字段:
(gdb) watch my_struct.field
支持条件观察:
(gdb) watch my_var if my_var > 100
支持设置 GDB 变量:
(gdb) set $p = &my_struct.field
(gdb) p *$p
7. GDB 内联函数无法直接调用
GDB 不能直接调用内联函数,如:
inline int get_count(struct list *l) { return l->count; }
(gdb) p get_count(&my_list) # ❌ 报错:未定义符号
解决方案:
- 将函数改为非
inline - 或在代码中主动加测试用入口函数(wrapper)
8. GDB 变量不能取地址
(gdb) set $x = 123
(gdb) p &$x # ❌ 错误:没有物理地址
只有程序中变量才能取地址:
(gdb) p &global_counter # ✅ 合法
如需有地址的临时变量,可用:
(gdb) set $buf = malloc(4)
(gdb) set *((int*)$buf) = 99
(gdb) p *(int*)$buf
9. 总结与建议
| 功能 | 命令 | 是否支持自动执行 |
|---|---|---|
| watch 变量变化 | watch(写) |
✅ 使用 commands |
| 读写监控地址 | rwatch(读)/awatch(读写) |
✅ 使用 commands |
| 打印调用位置 | frame + info line |
✅ |
| 清除命令 | commands N 后立即 end |
✅ |
建议
- 在 UT 场景中加断点太频繁容易卡断测试;建议用
watch+commands非侵入式追踪变量 - 若变量变化频繁,可用
if条件限制观察触发频率 - 避免在
commands中加入复杂逻辑,保持调试响应快速

浙公网安备 33010602011771号