代码之家  ›  专栏  ›  技术社区  ›  c-urchin

设置gdb硬件监视点/如何设置软件监视点

  •  18
  • c-urchin  · 技术社区  · 16 年前

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

    watch pObject->dPrice
    

    生产

    Hardware watchpoint 1: pObject->dPrice
    

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

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

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

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

    3 回复  |  直到 8 年前
        1
  •  17
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    是的,你可以:

    设置可以使用硬件观察点0

    5.1.2 Setting Watchpoints :

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

    set can-use-hw-watchpoints

    设置是否使用硬件监视点。

    show can-use-hw-watchpoints

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

        2
  •  7
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    我不是百分之百确定,但我的理解是当你看 pObject->dPrice ,gdb尝试监视任何可以更改监视值的内容。

    使用软件观察点,在每个步骤之后,gdb检查表达式是否已更改。使用硬件观察点,gdb必须为 dprice ,正如您所期望的,但也适用于 pObject .

    现在,您将问题标记为“x86”。在x86上,最多可以设置四个字节的断点。双精度是八个字节。如果你想看双人房,我想GDB需要两个硬件观察点。你需要一个额外的观察点 词库 也。我猜GDB想看 全部的 属于 词库 ,返回到问题中您链接的问题。

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

    p &pObject->dprice
    

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

    watch (double *) *0xabcdef10
    

    只看我想看的。

    注意:我前面没有打开gdb,因此我可能有 watch 命令错误(关于 * ,所以先看看。

        3
  •  6
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

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

    长回答: Quoting the GDB manual :

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

    gdb从字面上看这个表达式本身,而不是它指向的任何地址。在这种情况下,它意味着如果 pObject 它本身被改变为指向一个新的 dPrice 不只是一个观察点 pObject->dPrice 还有一个 词库 本身。这可能比现有的更多。

    更全面的例子:

    // 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 在上述程序中。

    在实践中,这是意想不到的,经常引发这个问题,而且通常不是您想要的。

    要只查看目标地址,请使用 监视-位置pobject->dprice . (从2011年7月发布的gdb 7.3开始提供;如果您使用的是旧的,请使用 print &pObject->dPrice watch *(double*)0x12345678 或打印的地址。)