gdb在while循环期间未执行断点命令



我有一个简单的C程序(如下所示(,它在一个循环中调用函数g5次,在函数g内部,它在循环中调用f10次(因此f总共调用了50次(。我正在尝试编写一个gdb脚本(也显示在下面(:

  1. g处设置断点
  2. 运行直到首次调用g
  3. g中的断点设置断点命令,以便下次到达g中的断点时,gdb退出
  4. 在函数f中设置断点
  5. 进入while循环,每次到达f时都会执行一些操作,然后继续(这必须是while循环而不是一组断点命令,因为这是一个更复杂情况的最小示例,每次到达内部函数中的断点时,我都有多个step/finish/continue命令,而使用断点命令是不可能的(

我观察到内部函数f中的断点已到达,但当gdb第二次到达g中的断点时,它不会执行我为g设置的命令(IEgdb不会退出(。程序继续执行并继续到下一次调用函数f,即使我在gdb提示符下键入info breakgdb也会显示我为g中的断点设置的命令。

我的问题:

  1. 为什么函数g中的断点命令没有被执行,即使gdb每次到达g中的断点时都会打印出来,而info break打印出与g关联的命令
  2. 如何更改gdb脚本,以便在第二次到达g中的断点时,gdb退出
  3. 也许,作为上一个问题的解决方案,是否有某种方法可以检查while循环中到达了哪个断点,如果它是g中的断点,则退出

下面是我的简单C程序和gdb脚本:

简单C程序

#include <stdio.h>
int i = 0;
void f() {
printf("in f(), i = %in", i++);
}
void g() {
printf("in g()n");
for (int j = 0; j < 10; j++) {
f();
}
}
int main() {
for (int j = 0; j < 5; j++) {
g();
}
}

gdb脚本

break g
run
delete
break g
commands
printf "gdb: in gn"
quit
end
break f
continue
while 1
printf "gdb: in fn"
continue
end
  1. 如何更改gdb脚本,以便在第二次到达g中的断点时,gdb退出

您可以使用此blah.txt脚本文件:

break g
ignore 1 1
run
quit
y

基本上就是说:

  • 中断g函数
  • 忽略该断点1次
  • 运行程序
  • 退出
  • 是的,我真的想辞职

使用:gcc -g -o blah blah.c构建blah.c文件

使用:gdb -x blah.txt blah运行

输出:

Breakpoint 1 at 0x1196: file blah.c, line 9.
in g()
in f(), i = 0
in f(), i = 1
in f(), i = 2
in f(), i = 3
in f(), i = 4
in f(), i = 5
in f(), i = 6
in f(), i = 7
in f(), i = 8
in f(), i = 9

Breakpoint 1, g () at blah.c:9
9       void g() {
A debugging session is active.

Inferior 1 [process 181] will be killed.

Quit anyway? (y or n) [answered Y; input not from terminal]

如果你想在任何时候点击fg断点时做一些工作,那么这个其他脚本可能会起作用:

  • 将布尔标志break_g_hit_before设置为false
  • g上断点的命令集定义为:
    print I’m ing
    检查break_g_hit_before是否为true,在这种情况下,退出gdb
    否则,将break_g_hit_before设置为true,然后继续
  • f上断点的命令集定义为:print I’m inf,然后继续
  • 跑步
set $break_g_hit_before = 0
break g
commands
printf "*** gdb: in gn"
if $break_g_hit_before
quit
y
end
set $break_g_hit_before = 1
continue
end
break f
commands
printf "### gdb: in fn"
continue
end
run

输出:

Breakpoint 1 at 0x1196: file blah.c, line 9.
Breakpoint 2 at 0x1169: file blah.c, line 5.
Breakpoint 1, g () at blah.c:9
9       void g() {
*** gdb: in g
in g()
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 0
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 1
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 2
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 3
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 4
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 5
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 6
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 7
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 8
Breakpoint 2, f () at blah.c:5
5       void f() {
### gdb: in f
in f(), i = 9
Breakpoint 1, g () at blah.c:9
9       void g() {
*** gdb: in g
A debugging session is active.
Inferior 1 [process 219] will be killed.
Quit anyway? (y or n) [answered Y; input not from terminal]

我有一种破解的解决方案,它在这种情况下有效(也在我感兴趣的更复杂的情况下有效,上面的问题是一个可重复的最小例子(。但它不一定在所有情况下都有效,例如,当在更高的堆栈帧中没有有效的计数器变量时,所以我将在这里发布它,但不接受它作为答案,同时等待更通用的解决方案。

诀窍如下:在while循环开始时,向上进入堆栈帧,查看main函数中的j计数器变量,并在j > 0之后立即退出gdb(这意味着g已被调用多次(。示例gdb脚本:

break g
run
delete
break f
continue
while 1
printf "gdb: in fn"
frame function main
if j > 0
quit
end
continue
end

最新更新