GDB:如何在函数返回后强制不删除观察点



函数局部变量上的监视点通常在函数返回时被删除,并显示消息«Watchpoint 7 delete because the program has leave the block in»。插图:

struct mystruct{
    int a, b, c;
};
void MyFunc(){
    mystruct obj;
    obj.a = 2;
}
int main(){
    MyFunc();
}

gdb会话示例

(gdb) b 7
Breakpoint 1 at 0x4004f1: file /tmp/test2.cpp, line 7.
(gdb) r
Starting program: /tmp/test2 
Breakpoint 1, MyFunc () at /tmp/test2.cpp:7
7               obj.a = 2;
(gdb) wa obj
Hardware watchpoint 2: obj
(gdb) c
Continuing.
Hardware watchpoint 2: obj
Old value = {a = 4195600, b = 0, c = 4195328}
New value = {a = 2, b = 0, c = 4195328}
MyFunc () at /tmp/test2.cpp:8
8       }
(gdb) c
Continuing.
Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
main () at /tmp/test2.cpp:12
12      }

我试着把它像wa *(mystruct *)&objwa *(mystruct *)(void*)&obj一样选角,但没有成功。

我需要它,因为我使用的嵌入式ARM设备上的GDB坏了:有时它会无故删除一个观察点;回溯看起来像是用"??"符号标记的行,以及关于损坏堆栈的消息。即使应用程序实际上很好。

正如GDB:设置监视点所说,

当局部(自动)变量或涉及此类变量的表达式超出范围时,即当执行离开定义这些变量的块时,GDB会自动删除监视点。

然而,从7.3版开始(感谢@Hi-Anger和IRC上的用户parcs指出了这一点;我错过了在文档中看到的内容),watch命令接受了-location参数:

通常,观察点尊重expr中变量的范围(见下文)。-location参数告诉GDB监视expr引用的内存。在这种情况下,GDB将计算expr,获取结果的地址,并监视该地址的内存。结果的类型用于确定监视的内存的大小。

在旧版本的GDB上,您可以使用问题中的示例运行此程序:

eval "watch *(mystruct *)%p", &obj

请注意,如果正在监视的内存被另一个函数的局部变量重用,则监视堆栈上的位置可能会导致虚假通知。

作为一种替代方案,您可以自动设置一个不断进出范围的自动变量的观察点。在作用域中的某个点设置断点,例如,在声明断点的函数或块的开头,然后附加watchcontinue命令:

(gdb) break MyFunc
(gdb) commands $bpnum
>watch obj
>continue
>end

最新更新