观察点类型

发布时间:2026/7/20 18:54:25
观察点类型 硬件观察点hardware watchpoint硬件观察点依赖CPU的调试寄存器来监控内存访问。当变量被修改时CPU会自动触发调试异常GDB就能在修改变量的位置停下来。硬件观察点的优点是效率高对程序运行性能影响很小而且通常能准确停在真正修改变量的那条指令附近。例如设置观察点后GDB 可能会提示(gdb) watch gdataHardware watchpoint 2: gdata这表示当前观察点是硬件观察点。2、软件观察点software watchpoint软件观察点则是GDB通过单步执行程序并在每一步之后检查表达式的值是否发生变化来实现的。因此软件观察点会明显降低程序运行速度尤其是在循环、递归、多线程程序中会更加明显。软件观察点是一种类似轮询的方式他不是CPU自动通知GDB变量变了而是GDB反复检查变量有没有变。大多数情况下GDB默认使用的都是硬件观察点不过需要注意虽然硬件观察点效率高但它并不是无限制使用的。硬件观察点依赖CPU的调试寄存器而调试寄存器的数量是有限的所以同时能够设置的硬件观察点数量也有限。不同CPU架构支持的数量可能不同通常只能设置少量几个硬件观察点。GDB默认会尽量使用硬件观察点。如果想查看当前是否允许使用硬件观察点可以使用(gdb) show can-use-hw-watchpoints如果想强制关闭硬件观察点让 GDB 使用软件观察点可以使用(gdb) set can-use-hw-watchpoints 0如果想重新开启硬件观察点可以使用(gdb) set can-use-hw-watchpoints 1一般情况下不需要手动修改这个选项保持默认即可。只有在研究软件观察点行为或者某些调试环境下硬件观察点异常时才需要手动设置。1.2 观察点常用命令命令 作用watch expr 写观察点当表达式的值发生变化时中断rwatch expr 读观察点当表达式被读取时中断awatch expr 访问观察点当表达式被读取或写入时中断i watchpoints 查看当前观察点信息也可以使用i b命令观察点和断点显示在同一个列表当中delete num 删除指定编号的观察点disable num 禁用指定编号的观察点enable num 启用指定编号的观察点其中watch最常用通常用来定位变量被修改的位置。rwatch和awatch使用频率相对较低主要用于排查某块数据在哪里被读取或访问。在实际使用中观察点常见于以下几类场景1、定位全局变量被谁修改当某个全局变量的值异常但是不清楚是哪段代码修改的可以使用(gdb) watch gdata程序运行过程中只要gdata的值发生变化GDB就会停下来并显示旧值和新值。2、定位结构体成员被谁修改例如有如下结构体struct Node {int id;int value;};struct Node node;如果想观察node.value是否被修改可以使用(gdb) watch node.value如果是结构体指针struct Node *pnode;则可以使用(gdb) watch pnode-value3、定位数组元素被谁修改如果只关心数组中的某一个元素可以直接观察指定下标(gdb) watch arr[3]这样只有arr[3]的值发生变化时才会中断修改数组中的其他元素不会触发这个观察点。4、定位多线程中的共享变量修改在多线程程序中多个线程可能都会修改同一个共享变量。如果想知道到底是哪个线程修改了变量可以设置观察点(gdb) watch gdata当gdata被修改时程序会停下来。此时可以使用(gdb) info threads(gdb) bt查看当前是哪个线程触发了观察点以及对应的函数调用栈。如果只想观察某一个线程对变量的修改可以使用(gdb) watch gdata thread 3这表示只有GDB中编号为3的线程修改gdata时才会触发观察点。线程编号可以通过下面命令查看(gdb) info threads5、观察变量计算式观察点不仅可以观察单个变量也可以观察由多个变量组成的计算表达式。当表达式的计算结果发生变化时程序就会中断下来。例如(gdb) watch a b表示观察表达式a b的值。当a或b的值发生变化并且导致a b的计算结果发生变化时GDB就会停下来。示例代码#include stdio.hint main(){int a 1;int b 2;a 3; // a b 从 3 变成 5会触发观察点 b 4; // a b 从 5 变成 7会触发观察点 printf(a b %d\n, a b); return 0;}调试时可以这样设置(gdb) r(gdb) watch a b(gdb) continue当a b的结果发生变化时GDB会中断下来并显示表达式的旧值和新值。除了普通计算表达式也可以观察条件表达式(gdb) watch a b 10这表示观察表达式a b 10的结果是否发生变化。由于这是一个布尔表达式所以结果只有两种真或假。需要注意watch a b 10并不是表示“只要a b 10就停下来”而是表示“当 a b 10这个表达式的结果发生变化时停下来”。二、捕获点捕获点catchpoint也是一种特殊的断点。普通断点通常是在程序执行到某一行代码或某个函数时中断观察点是在某个表达式的值发生变化时中断而捕获点关注的是某类事件是否发生。捕获点的命令语法为catch event含义是当程序运行过程中捕获到指定的 event 事件时程序就会中断下来。捕获点和普通断点、观察点一样也会被 GDB 分配编号因此可以使用 info breakpoints、delete、disable、enable 等命令进行管理。2.1 常用捕获点命令常见的捕获点事件如下