设置GDB硬件观察点/如何设置软件观察点

时间:2010-08-12 18:15:25

标签: c++ linux gdb x86

An earlier question解释说,在x86上,被监视对象的大小受调试寄存器的限制。正如所料,我可以“观察”一个双变量。但我无法观看双数据,例如,

watch pObject->dPrice

产生

Hardware watchpoint 1: pObject->dPrice

但是当你试图继续执行时,它会说

  

无法插入硬件断点:   您可能已经请求了太多硬件断点/观察点。

即使这只是 断点/观察点。

我很好奇为什么会这样,但更重要的是有办法吗?根据GDB文档,如果它不能使用硬件,它可能会使用软件观察点。在这种情况下,它不会尝试使用软件观察点 - 有没有办法强制它这样做?

3 个答案:

答案 0 :(得分:18)

是的,你可以:

  

设置can-use-hw-watchpoints 0

来自5.1.2 Setting Watchpoints

  

您可以强制GDB仅使用set can-use-hw-watchpoints 0命令使用软件观察点。将此变量设置为零,GDB将永远不会尝试使用硬件观察点,即使底层系统支持它们也是如此。 (请注意,在将can-use-hw-watchpoints设置为零之前设置的硬件辅助观察点仍将使用观察表达式值的硬件机制。)

set can-use-hw-watchpoints

设置是否使用硬件观察点。

show can-use-hw-watchpoints

显示使用硬件观察点的当前模式。

答案 1 :(得分:7)

我不是百分百肯定,但我的理解是,当您观看pObject->dPrice时,GDB会尝试观看任何可以改变观看值的内容。

使用软件观察点,在每个步骤之后,GDB检查表达式是否已更改。使用硬件观察点,GDB必须按照您的预期为dprice设置观察点,同时也为pObject设置观察点。

现在,您标记了问题'x86'。在x86上,您可以设置最多四个字节的断点。双精度是八个字节。如果你想看一个双,我猜想GDB需要两个硬件观察点。您还需要pObject的额外观察点。我猜测GDB会尝试观看pObject所有,这会回到您在问题中链接的问题中的问题。

当我想做类似的事情时,如果我确定指针pObject不会改变,我通常会这样做:

p &pObject->dprice

我们说GDB说地址是(double *) 0xabcdef10,现在我做了:

watch (double *) *0xabcdef10

只看我想要的东西。

注意:我没有在我面前打开GDB,因此watch命令的确切语法错误(关于*的位置),所以请查看第一

答案 2 :(得分:6)

简答:使用watch -location pObject->dPrice或简写watch -l

答案很长:Quoting the GDB manual

  

观察引用许多变量的复杂表达式也会耗尽可用于硬件辅助观察点的资源。那是因为GDB需要使用单独分配的资源来观察表达式中的每个变量。

GDB完全按照字面意思观察表达本身,而不是它指向的任何地址。在这种情况下,这意味着如果将pObject本身更改为指向新的dPrice,则会触发断点; pObject->dPrice不仅仅是pObject的观察点,也是// Set a watchpoint on '*p' before running #include <stdio.h> int a = 0; int b = 0; int c = 0; int* p = &a; int main() { puts("Hi"); // Dummy lines to make the results clearer, watchpoints stop at the line after the change *p = 1; // Breaks: *p was changed from 0 to 1 puts("Hi"); a = 2; // Breaks: a is *p, which changed from 1 to 2 puts("Hi"); p = &b; // Breaks: p is now b, changing *p from 2 to 0 puts("Hi"); p = &c; // Doesn't break: while p changed, *p is still 0 puts("Hi"); p = NULL; // Breaks: *p is now unreadable puts("Hi"); return 0; } 本身的观察点。这可能比现有的更多。

更全面的例子:

watch a==b

从理论上讲,这是一个有用的功能;你可以看到一个复杂的表达,一旦它是错误的,就会破坏,有点像一个经常被测试的断言。例如,您可以在上述程序中watch -location pObject->dPrice

在实践中,这是意料之外的,经常触发这个问题,通常不是你想要的。

要仅查看目标地址,请使用print &pObject->dPrice。 (从2011年7月发布的GDB 7.3开始提供;如果您使用的是旧版本,请使用watch *(double*)0x12345678DELETE t1 FROM table t1 JOIN (SELECT RESPONSEOID FROM table GROUP BY RESPONSEOID HAVING(COUNT(IF(Statuses = 'Finalizado', 1, null))) = 0 ) t2 ON t1.RESPONSEOID = t2.RESPONSEOID; ,或打印的任何地址。)