C++ 如何在函数返回的 GDB 中设置断点?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3649468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set a breakpoint in GDB where the function returns?
提问by avd
I have a C++ function which has many return statements at various places. How to set a breakpoint at the return statement where the function actually returns ?
我有一个 C++ 函数,它在不同的地方有很多 return 语句。如何在函数实际返回的 return 语句处设置断点?
And what does "break" command without argument means?
没有参数的“break”命令是什么意思?
采纳答案by Jim Brissom
break without arguments stops execution at the next instruction in the currently selected stack frame. You select strack frames via the frame
or up
and down
commands. If you want to debug the point where you are actuallyleaving the current function, select the next outer frame and break there.
不带参数的 break 在当前选定堆栈帧中的下一条指令处停止执行。您可以通过frame
或up
和down
命令选择跟踪帧。如果要调试实际离开当前函数的点,请选择下一个外部框架并在那里中断。
回答by Employed Russian
Contrary to answers so far, most compilers will create a single return assembly instruction, regardless of how many return
statements are in the function (it is convenient for the compiler to do that, so there is only a single place to perform all the stack frame cleanup).
与目前的答案相反,大多数编译器都会创建一条返回汇编指令,无论return
函数中有多少条语句(编译器这样做很方便,因此只有一个地方可以执行所有堆栈帧清理)。
If you wanted to stop on that instruction, all you have to do is disas
and look for retq
(or whatever the return instruction for your processor is), and set a breakpoint on it. For example:
如果您想在该指令上停止,您所要做的就是disas
寻找retq
(或任何处理器的返回指令),并在其上设置断点。例如:
int foo(int x)
{
switch(x) {
case 1: return 2;
case 2: return 3;
default: return 42;
}
}
int main()
{
return foo(0);
}
(gdb) disas foo
Dump of assembler code for function foo:
0x0000000000400448 <+0>: push %rbp
0x0000000000400449 <+1>: mov %rsp,%rbp
0x000000000040044c <+4>: mov %edi,-0x4(%rbp)
0x000000000040044f <+7>: mov -0x4(%rbp),%eax
0x0000000000400452 <+10>: mov %eax,-0xc(%rbp)
0x0000000000400455 <+13>: cmpl (gdb) record
(gdb) fin
(gdb) reverse-step
x1,-0xc(%rbp)
0x0000000000400459 <+17>: je 0x400463 <foo+27>
0x000000000040045b <+19>: cmpl void on_return() {
}
#define return return on_return(), /* If the function has a return value != void */
#define return return on_return() /* If the function has a return value == void */
/* <<<-- Insert your function here -->>> */
#undef return
x2,-0xc(%rbp)
0x000000000040045f <+23>: je 0x40046c <foo+36>
0x0000000000400461 <+25>: jmp 0x400475 <foo+45>
0x0000000000400463 <+27>: movl #include <stdio.h>
/* Dummy function to place the breakpoint */
void on_return(void) {
}
#define return return on_return()
void myfun1(int a) {
if (a > 10) return;
printf("<10\n");
return;
}
#undef return
#define return return on_return(),
int myfun2(int a) {
if (a < 0) return -1;
if (a > 0) return 1;
return 0;
}
#undef return
int main(void)
{
myfun1(1);
myfun2(2);
}
x2,-0x8(%rbp)
0x000000000040046a <+34>: jmp 0x40047c <foo+52>
0x000000000040046c <+36>: movl return;
x3,-0x8(%rbp)
0x0000000000400473 <+43>: jmp 0x40047c <foo+52>
0x0000000000400475 <+45>: movl return on_return();
x2a,-0x8(%rbp)
0x000000000040047c <+52>: mov -0x8(%rbp),%eax
0x000000000040047f <+55>: leaveq
0x0000000000400480 <+56>: retq
End of assembler dump.
(gdb) b *0x0000000000400480
Breakpoint 1 at 0x400480
(gdb) r
Breakpoint 1, 0x0000000000400480 in foo ()
(gdb) p $rax
= 42
回答by ks1322
You can use reverse debuggingto find out where function actually returns. Finish executing current frame, do reverse-stepand then you should stop at just returned statement.
您可以使用反向调试来找出函数实际返回的位置。执行完当前帧,做反向步骤,然后你应该在刚刚返回的语句处停止。
return -1;
回答by Potatoswatter
Break without argument sets a breakpoint at the current line.
Break without argument 在当前行设置断点。
There is no way for a single breakpoint to catch all return paths. Either set a breakpoint at the caller immediately after it returns, or break at all return
statements.
单个断点无法捕获所有返回路径。要么在调用者返回后立即在调用者处设置断点,要么在所有return
语句处中断。
Since this is C++, I suppose you could create a local sentry object, and break on its destructor, though.
由于这是 C++,我想您可以创建一个本地哨兵对象,然后中断其析构函数。
回答by urzeit
If you can change the source code, you might use some dirty trick with the preprocessor:
如果您可以更改源代码,您可能会在预处理器中使用一些肮脏的技巧:
return on_return(), -1;
Then set a breakpoint to on_return
and go one frame up
.
然后将断点设置为on_return
并转到一帧up
。
Attention: This will not work, if a function does not return via a return
statement. So ensure, that it's last line is a return
.
注意:如果函数不通过return
语句返回,这将不起作用。所以确保它的最后一行是一个return
.
Example (shamelessly copied from C code, but will work also in C++):
示例(无耻地从 C 代码复制,但也适用于 C++):
##代码##The first macro will change
第一个宏会改变
##代码##to
到
##代码##Which is valid, since on_return
also returns void
.
这是有效的,因为on_return
也返回void
.
The second macro will change
第二个宏会改变
##代码##to
到
##代码##Which will call on_return()
and then return -1 (thanks to the ,
-operator).
它将调用on_return()
然后返回 -1(感谢,
-operator)。
This is a very dirty trick, but despite using backwards-stepping, it will work in multi-threaded environments and inlined functions, too.
这是一个非常肮脏的技巧,但尽管使用了向后步进,它也可以在多线程环境和内联函数中工作。