我正在Linux上的gdb 7.1中调试C ++。
我有一个在代码中很多地方调用的函数a()
。我想在其中设置一个断点,但前提是它是从b()
调用的。有没有办法做到这一点?
只有在b()
调用c()
时才有办法执行此操作,以此类推,无限期?
答案 0 :(得分:23)
更新:此问题现在有better answer:使用GDB _is_caller
便利功能。
您描述的需求经常出现,通常是在some_utility_fn
被大量调用的情况下,但您只对来自some_other_fn
的调用感兴趣。
你可以使用CVS trunk中GDB中新的嵌入式Python支持编写整个交互的脚本。
没有Python,你可以做的事情有限,但通常的技术是在a()
上有一个禁用的断点,并从附加到断点的命令启用它在b()
。
以下是一个例子:
int a(int x)
{
return x + 1;
}
int b()
{
return a(1);
}
int call_a_lots()
{
int i, sum = 0;
for (i = 0; i < 100; i++)
sum += a(i);
}
int main()
{
call_a_lots();
return b();
}
gcc -g t.c
gdb -q ./a.out
Reading symbols from /tmp/a.out...done.
(gdb) break a
Breakpoint 1 at 0x4004cb: file t.c, line 3.
(gdb) disable 1
(gdb) break b
Breakpoint 2 at 0x4004d7: file t.c, line 8.
(gdb) command 2
>silent
>enable 1
>continue
>end
(gdb) run
Breakpoint 1, a (x=1) at t.c:3
3 return x + 1;
(gdb) bt
#0 a (x=1) at t.c:3
#1 0x00000000004004e1 in b () at t.c:8
#2 0x000000000040052c in main () at t.c:21
(gdb) q
Voila:我们已经停止a()
来自b()
,忽略之前100次拨打a()
。
答案 1 :(得分:8)
我已经在已经可用的gdb 7.6上测试了这个,但是它不能在gdb 7.2上运行,可能在gdb 7.1上运行:
所以这是main.cpp:
int a()
{
int p = 0;
p = p +1;
return p;
}
int b()
{
return a();
}
int c()
{
return a();
}
int main()
{
c();
b();
a();
return 0;
}
然后g ++ -g main.cpp
这是my_check.py:
class MyBreakpoint (gdb.Breakpoint):
def stop (self):
if gdb.selected_frame().older().name()=="b":
gdb.execute("bt")
return True
else:
return False
MyBreakpoint("a")
这就是它的工作原理:
4>gdb -q -x my_check.py ./a.out
Reading symbols from /home/a.out...done.
Breakpoint 1 at 0x400540: file main.cpp, line 3.
(gdb) r
Starting program: /home/a.out
#0 a () at main.cpp:3
#1 0x0000000000400559 in b () at main.cpp:10
#2 0x0000000000400574 in main () at main.cpp:21
Breakpoint 1, a () at main.cpp:3
3 int p = 0;
(gdb) c
Continuing.
[Inferior 1 (process 16739) exited normally]
(gdb) quit
答案 2 :(得分:5)
比Python脚本更简单的解决方案是使用temporary breakpoint。
看起来像这样:
b ParentFunction
command 1
tb FunctionImInterestedIn
c
end
每次进入ParentFunction
时,您都会在您真正感兴趣的功能上设置一次性断点,然后继续运行(可能直到您达到该断点)。 / p>
由于您在FunctionImInterestedIn
上只打破一次,如果在FunctionImInterestedIn
的上下文中多次调用ParentFunction
并且您想要破解,则无法工作每次调用。
答案 3 :(得分:3)
不确定gdb是怎么做的 但是你可以声明全局变量,如:
bool call_a = false;
当b调用
时call_a = true;
a();
并在其他函数调用a()或断点
之后将call_a设置为false然后使用条件断点
break [line-number] if call_a == true
答案 4 :(得分:2)
gdb现在可以直接处理这个,而不需要Python。就这样做:
b a if $_caller_is("b")
答案 5 :(得分:0)
一个简单的手臂是:
在您感兴趣的函数中设置断点。
break a
将gdb命令附加到该断点。
command 1
up 1
if $lr == 0x12345678
echo match \n
down 1
else
echo no match \n
echo $lr \n
down 1
cont
end
end
当你到达函数a()时,命令暂时弹出一个堆栈帧,从而更新链接寄存器。然后,当调用者不执行时,可以继续使用调用者链接寄存器值 你需要的道路。
享受。