用 Watch 窗口观察变量变化 —— 实时监控关键数据
Watch 是什么
Watch 窗口是调试面板里的一个区域,让你手动添加变量或表达式,持续观察它们的值。和自动显示的「当前作用域变量」不同,Watch 窗口里的内容不受作用域限制——即使你 Step Out 出了当前函数,只要那个变量还在调用栈某帧存在,Watch 窗口就能继续显示它的值。
添加 Watch 表达式
典型操作流程:
- 点击调试面板里 Watch 区域的「添加」按钮
- 输入变量名或表达式:
counter、*ptr、user.score * 2 - 回车确认,表达式就出现在 Watch 列表里
- 每一次单步执行(Step Over / Step Into / Continue),Watch 列表自动刷新值
适用场景
循环中观察变量变化
for (int i = 0; i < 10; ++i) {
int result = slowCompute(i); ← 这里可能挂了
saveResult(result);
}
在循环开始前加 Watch: result,然后 Continue 循环(或者在循环体内设断点 + Continue)。每次循环回来 Watch 窗口就刷新 result 的值——你能一眼看到哪个迭代出了问题。
跨函数追踪参数变化
void process(int value) {
modify(value);
validate(value);
}
在调用方加 Watch: value,Step Into process 后 Watch 窗口里还能继续看到 value 的变化——你就能追踪 value 在 modify 和 validate 调用后分别变成了什么。
监控指针解引用
Node *head = createList();
traverse(head); ← 这里 crash 了,但不确定 head 是不是 null
在 Watch 里加 *head(如果 head 不是 null)或 head->next——如果这些表达式能正常显示,说明指针有效;如果报 memory unavailable,说明指针有问题。
限制
Watch 表达式能接受的语法取决于 gdb 的配置:
- 大多数基本表达式(算术、逻辑、解引用、成员访问)都支持
- 模板参数(
std::vector<int>::value_type)可能不支持 - lambda 表达式不支持
- 某些复杂的模板调用(
boost::any_cast<T>(obj))可能有问题
如果某个表达式一直报 error,简化它试试——比如把函数调用的结果先赋给一个临时变量,然后 Watch 那个临时变量。
Watch 变量 vs 直接打印
// 方法一:Watch 窗口
for (int i = 0; i < 100; ++i) {
process(i); // Watch: i, result(实时更新)
}
// 方法二:加 cout 打印
for (int i = 0; i < 100; ++i) {
int result = process(i);
std::cout << "i=" << i << " result=" << result << "\n";
}
| 维度 | Watch 窗口 | cout 打印 |
|---|---|---|
| 编译开销 | 无(调试器层面) | 需要重编译加打印 |
| 信息量 | 当前值,可随时停止 | 只能看历史日志 |
| 性能 | 几乎为零 | 大量 IO 输出可能拖慢 |
| 退出循环后的查看 | 还在 Watch 里 | print 完就没了 |
调试阶段用 Watch;需要长期留痕的日志用 cout(或更好的 logging 库)。