An earlier question解释说,在x86上,被监视对象的大小受调试寄存器的限制。正如所料,我可以“观察”一个双变量。但我无法观看双数据,例如,
watch pObject->dPrice
产生
Hardware watchpoint 1: pObject->dPrice
但是当你试图继续执行时,它会说
无法插入硬件断点: 您可能已经请求了太多硬件断点/观察点。
即使这只是 断点/观察点。
我很好奇为什么会这样,但更重要的是有办法吗?根据GDB文档,如果它不能使用硬件,它可能会使用软件观察点。在这种情况下,它不会尝试使用软件观察点 - 有没有办法强制它这样做?
答案 0 :(得分:18)
是的,你可以:
设置can-use-hw-watchpoints 0
您可以强制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*)0x12345678
和DELETE 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;
,或打印的任何地址。)