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

c-u*_*hin 19 c++ linux x86 gdb

之前的一个问题解释说,在x86上,被监视对象的大小受调试寄存器的限制.正如所料,我可以"观察"一个双变量.但我不能看一个双数据,例如,

watch pObject->dPrice
Run Code Online (Sandbox Code Playgroud)

产生

Hardware watchpoint 1: pObject->dPrice
Run Code Online (Sandbox Code Playgroud)

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

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

即使这是唯一的断点/观察点.

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

kar*_*lip 19

是的你可以:

设置can-use-hw-watchpoints 0

5.1.2设置观察点:

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

set can-use-hw-watchpoints

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

show can-use-hw-watchpoints

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

  • 它可以工作,但它比硬件慢一点。就我而言,大约是速度的 1/5000。 (2认同)

Alc*_*aro 8

简短回答:使用watch -location pObject->dPrice,或简短形式watch -l.

答案很长:引用GDB手册:

观察引用许多变量的复杂表达式也会耗尽可用于硬件辅助观察点的资源.那是因为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;
}
Run Code Online (Sandbox Code Playgroud)

从理论上讲,这是一个有用的功能; 你可以看一个复杂的表达,一旦它是错误的,就会破坏,有点像一个经常被测试的断言.例如,您可以watch a==b在上面的程序中.

在实践中,它是出乎意料的,经常触发这个问题,通常不是你想要的.

要仅查看目标地址,请使用watch -location pObject->dPrice.(这是从2011年7月发布的GDB 7.3开始提供的;如果您使用的是旧版本,请使用print &pObject->dPricewatch *(double*)0x12345678,或者打印的任何地址.)


Nat*_*man 7

我不是百分百肯定,但我的理解是,当你观看时pObject->dPrice,GDB会尝试观看任何可以改变观看价值的东西.

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

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

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

p &pObject->dprice
Run Code Online (Sandbox Code Playgroud)

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

watch (double *) *0xabcdef10
Run Code Online (Sandbox Code Playgroud)

并只看我想要的东西.

注意:我没有在我面前打开GDB,所以我可能有watch错误的命令的确切语法(关于放置*),所以首先检查它.

  • @CraigRinger:[确实如此.](http://stackoverflow.com/questions/25938830/gdb-how-to-force-a-watchpoint-to-not-be-deleted-after-a-function-returned)观看-location pObject-> dprice` (3认同)
  • 如果gdb提供了"只观看最终目标"的快捷方式,那就太好了 (2认同)