有没有办法在程序达到一定帧数后中断程序?

Is there a way to break a program after it reaches a certain number of frames?

我正在尝试实现一个递归树函数,但出现段错误,因为该函数会自行调用,我想看看我的程序最后处于什么状态。

I would like to see what state my program is at the end.

运行 GDB下的程序,它会停止(当你的程序耗尽它的堆栈时)并且显示你最后的状态。

示例:

void fn(int j)
{
  char buf[1024];  // consume some stack space.
  buf[0] = 'a';
  fn(j - buf[0]);  // bad recursion -- should have checked for j - 'a' > 0
}

int main()
{
  fn(10000);
  return 0;
}
gcc -g t.c && gdb -q ./a.out
(gdb) run
Starting program: /tmp/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x0000555555555130 in fn (j=<error reading variable: Cannot access memory at address 0x7fffff7fef8c>) at t.c:2
2       {
(gdb) bt 10
#0  0x0000555555555130 in fn (j=<error reading variable: Cannot access memory at address 0x7fffff7fef8c>) at t.c:2
#1  0x0000555555555158 in fn (j=-759889) at t.c:5
#2  0x0000555555555158 in fn (j=-759792) at t.c:5
#3  0x0000555555555158 in fn (j=-759695) at t.c:5
#4  0x0000555555555158 in fn (j=-759598) at t.c:5
#5  0x0000555555555158 in fn (j=-759501) at t.c:5
#6  0x0000555555555158 in fn (j=-759404) at t.c:5
#7  0x0000555555555158 in fn (j=-759307) at t.c:5
#8  0x0000555555555158 in fn (j=-759210) at t.c:5
#9  0x0000555555555158 in fn (j=-759113) at t.c:5
(More stack frames follow...)

你在这里看到的是程序最后的状态,即完全你在[=43]中要求的=],但不在标题中(在 body 和标题中提出 不同的 问题是一种不好的形式)。

Is there a way to break a program after it reaches a certain number of frames?

没有,但有各种近似值。

对于上面的测试程序,答案是微不足道的。由于 fn 不断调用自身,您可以在第 N 次调用时停止。例如。如果您想在递归达到 100 帧时停止,请执行以下操作:

(gdb) b fn
Breakpoint 1 at 0x1136: file t.c, line 4.
(gdb) ign 1 100
Will ignore next 100 crossings of breakpoint 1.
(gdb) run
Starting program: /tmp/a.out 

Breakpoint 1, fn (j=300) at t.c:4
4         buf[0] = 'a';
(gdb) bt
#0  fn (j=300) at t.c:4
#1  0x0000555555555158 in fn (j=397) at t.c:5
#2  0x0000555555555158 in fn (j=494) at t.c:5
#3  0x0000555555555158 in fn (j=591) at t.c:5
#4  0x0000555555555158 in fn (j=688) at t.c:5
...
#99 0x0000555555555158 in fn (j=9903) at t.c:5
#100 0x0000555555555158 in fn (j=10000) at t.c:5
#101 0x0000555555555169 in main () at t.c:10

fn间接调用自身时,事情会变得更复杂(但如果循环的长度是固定的K,那么只需将N除以K)。

如果循环的长度不是固定的,或者如果某些调用 return(即不是每个调用都重复出现),那么达到 N 级深度会稍微复杂一些。最简单的方法是修改程序以在全局范围内保持递归计数。然后你可以简单地设置一个条件观察点。示例:

int recursion_count;

void fn(int j)
{
  char buf[1024];  // consume some stack space.

  recursion_count += 1;
  buf[0] = 'a';
  fn(j - buf[0]);  // bad recursion -- should have checked for j - 'a' > 0
  recursion_count -= 1;
}

int main()
{
  fn(10000);
  return 0;
}
gcc -g t.c && gdb -q ./a.out
(gdb) start
Temporary breakpoint 1 at 0x55555555517d: file t.c, line 15.
Starting program: /tmp/a.out 

Temporary breakpoint 1, main () at t.c:15
15        fn(10000);
(gdb) p recursion_count
 = 0
(gdb) watch recursion_count
Hardware watchpoint 2: recursion_count
(gdb) cond 2 recursion_count == 100
(gdb) c
Continuing.

Hardware watchpoint 2: recursion_count

Old value = 99
New value = 100
fn (j=397) at t.c:8
8         buf[0] = 'a';
(gdb) bt 
#0  fn (j=397) at t.c:8
#1  0x0000555555555167 in fn (j=494) at t.c:9
#2  0x0000555555555167 in fn (j=591) at t.c:9
#3  0x0000555555555167 in fn (j=688) at t.c:9
...
#97 0x0000555555555167 in fn (j=9806) at t.c:9
#98 0x0000555555555167 in fn (j=9903) at t.c:9
#99 0x0000555555555167 in fn (j=10000) at t.c:9
#100 0x0000555555555187 in main () at t.c:15

瞧。