当只有一个时,gdb停止有太多观察点

时间:2010-07-08 17:32:48

标签: gdb

除了太多的硬件断点/观察点之外,您是否知道为什么无法插入观察点?

我有以下调试会话:

GNU gdb (GDB) 7.1
...
(gdb) watch itrap_t_beg[1][222]
Hardware watchpoint 1: itrap_t_beg[1][222]
(gdb) cont
Continuing.
...
Hardware watchpoint 1: itrap_t_beg[1][222]

...
(gdb) cont
Continuing.
Warning:
Could not insert hardware watchpoint 1.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.

(gdb) info break
Num     Type           Disp Enb Address            What
1       hw watchpoint  keep y                      itrap_t_beg[1][222]
        breakpoint already hit 1 time

如您所见,只有一个观察点但它无法插入断点。

你知道我该如何解决这个问题吗?

3 个答案:

答案 0 :(得分:12)

据我所知,商品x86 CPU有四个debug registers可用于支持硬件中断/监视。这会限制您可以观看的对象大小。对象对齐也在这里播放。

尝试将手表范围限制为较小的对象,例如结构的第一个和最后一个成员对。

答案 1 :(得分:8)

可以通过运行

强制软件断点(没有大小限制)

设置can-use-hw-watchpoints 0

答案 2 :(得分:1)

拍摄答案:使用watch -location itrap_t_beg[1][222]或短格式watch -l

答案很长:Quoting the GDB manual

  

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

gdb完全按字面意思观察表达本身,而不是它指向的任何地址。在这种情况下,这意味着如果itrap_t_beg本身发生更改,断点将会点击,itrap_t_beg[1][222]会这样做;这不仅是itrap_t_beg[1][222]的观察点,也是itrap_t_beg本身的观察点。这可能不仅仅是可用的。

在您的情况下,itrap_t_beg是7个字节,28个字节。 x86_64观察点最多为8个字节,因此GDB需要整个结构的四个观察点 - 加上itrap_t_beg本身的五分之一。 x86系列仅支持四个同时观察点。

关于观察点如何运作的更全面的例子:

//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 itrap_t_beg[1][222]。 (从2011年7月发布的GDB 7.3开始提供;如果您仍然使用7.1,请使用print &itrap_t_beg[1][222]watch *(itrap_t)0x12345678,或者打印的地址。)