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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:22:45  来源:igfitidea点击:

How to set a breakpoint in GDB where the function returns?

c++debugginggdb

提问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 frameor upand downcommands. If you want to debug the point where you are actuallyleaving the current function, select the next outer frame and break there.

不带参数的 break 在当前选定堆栈帧中的下一条指令处停止执行。您可以通过frameupdown命令选择跟踪帧。如果要调试实际离开当前函数的点,请选择下一个外部框架并在那里中断。

回答by Employed Russian

Contrary to answers so far, most compilers will create a single return assembly instruction, regardless of how many returnstatements 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 disasand 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 returnstatements.

单个断点无法捕获所有返回路径。要么在调用者返回后立即在调用者处设置断点,要么在所有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_returnand go one frame up.

然后将断点设置为on_return并转到一帧up

Attention: This will not work, if a function does not return via a returnstatement. 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_returnalso 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.

这是一个非常肮脏的技巧,但尽管使用了向后步进,它也可以在多线程环境和内联函数中工作。