我有一个简单的C程序(如下所示(,它在一个循环中调用函数g
5次,在函数g
内部,它在循环中调用f
10次(因此f
总共调用了50次(。我正在尝试编写一个gdb
脚本(也显示在下面(:
- 在
g
处设置断点 - 运行直到首次调用
g
- 为
g
中的断点设置断点命令,以便下次到达g
中的断点时,gdb
退出 - 在函数
f
中设置断点 - 进入while循环,每次到达
f
时都会执行一些操作,然后继续(这必须是while循环而不是一组断点命令,因为这是一个更复杂情况的最小示例,每次到达内部函数中的断点时,我都有多个step
/finish
/continue
命令,而使用断点命令是不可能的(
我观察到内部函数f
中的断点已到达,但当gdb
第二次到达g
中的断点时,它不会执行我为g
设置的命令(IEgdb
不会退出(。程序继续执行并继续到下一次调用函数f
,即使我在gdb
提示符下键入info break
,gdb
也会显示我为g
中的断点设置的命令。
我的问题:
- 为什么函数
g
中的断点命令没有被执行,即使gdb
每次到达g
中的断点时都会打印出来,而info break
打印出与g
关联的命令 - 如何更改
gdb
脚本,以便在第二次到达g
中的断点时,gdb
退出 - 也许,作为上一个问题的解决方案,是否有某种方法可以检查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
- 如何更改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]
如果你想在任何时候点击f
和g
断点时做一些工作,那么这个其他脚本可能会起作用:
- 将布尔标志
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