1

当特定变量设置为特定值时,有什么方法可以让 gdb 暂停?例如,如果在某个范围内有一个变量 x,它在程序执行的某个时刻被设置为 4。当 x 设置为 4 时,如何指示 gdb 暂停执行?

4

1 回答 1

4

当特定变量设置为特定值时,有什么方法可以让 gdb 暂停?

是的:您可以设置观察点,并且可以使其有条件。

首先是一个简单的例子:变量是全局的(因此它的地址永远不会改变):

$ cat tt.c
int foo;

void bar() { foo += 1; }
void baz() { foo += 2; }

int main()
{
  baz(); bar(); baz();
  return 0;
}
$ gcc -g tt.c && gdb -q ./a.out
Reading symbols from /tmp/a.out...done.
(gdb) watch foo
Hardware watchpoint 1: foo
(gdb) cond 1 foo == 3
(gdb) r
Starting program: /tmp/a.out
Hardware watchpoint 1: foo

Old value = 2
New value = 3
0x00000000004004c7 in bar () at tt.c:3
3   void bar() { foo += 1; }
(gdb) quit

第二个简单的例子:变量是本地的,并且总是驻留在同一个堆栈位置:

$ cat t.c
int main()
{
  int i, sum = 0;

  for (i = 0; i < 10; ++i) {
    sum += i;
  }

  return 0;
}
$ gcc -g t.c && gdb -q ./a.out
Reading symbols from /tmp/a.out...done.
(gdb) b 5
Breakpoint 1 at 0x4004bf: file t.c, line 5.
(gdb) r
Starting program: /tmp/a.out

Breakpoint 1, main () at t.c:5
5     for (i = 0; i < 10; ++i) {
(gdb) watch sum
Hardware watchpoint 2: sum
(gdb) cond 2 sum == 36
(gdb) c
Continuing.
Hardware watchpoint 2: sum

Old value = 28
New value = 36
main () at t.c:5
5     for (i = 0; i < 10; ++i) {
(gdb) quit

最后,一个棘手的情况:局部变量在堆栈上的位置发生了变化(例如,因为它所在的函数被递归调用,或者从不同的上下文中调用):

$ cat foo.c
int foo(int x)
{
  int y = x + x;
  return y;
}

int recursive(int x, int y)
{
  if (x > 0)
    return recursive(x - 1, y + 1);
  return foo(y);
}

int main()
{
  printf("recursive(1,0) = %d\n", recursive(1, 0));
  printf("recursive(2,0) = %d\n", recursive(2, 0));
  printf("recursive(3,0) = %d\n", recursive(3, 0));
  return 0;
}

$ gcc -g foo.c && gdb -q ./a.out

(gdb) b foo
Breakpoint 1 at 0x4004fb: file foo.c, line 3.
(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>watch y
>cond $bpnum y == 4
>c
>end
(gdb) r
Starting program: /tmp/a.out

Breakpoint 1, foo (x=1) at foo.c:3
3     int y = x + x;
Hardware watchpoint 2: y

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
recursive (x=0, y=1) at foo.c:12
12  }

这里 GDB 停止了,因为观察点无效。我不知道如何让它静默删除观察点并继续。

(gdb) c
Continuing.
recursive(1,0) = 2

Breakpoint 1, foo (x=2) at foo.c:3
3     int y = x + x;
Hardware watchpoint 3: y
Hardware watchpoint 3: y

Old value = 0
New value = 4
foo (x=2) at foo.c:4
4     return y;

达达!

(gdb) bt
#0  foo (x=2) at foo.c:4
#1  0x000000000040053d in recursive (x=0, y=2) at foo.c:11
#2  0x0000000000400531 in recursive (x=1, y=1) at foo.c:10
#3  0x0000000000400531 in recursive (x=2, y=0) at foo.c:10
#4  0x0000000000400572 in main () at foo.c:17
于 2013-03-31T20:17:19.073 回答