在Linux上以编程方式在C或C ++代码中为gdb设置断点


103

如何在C或C ++代码中以编程方式设置一个断点,该断点将在Linux上适用于gdb?

即:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}

8
非常有旁注(对nitpick很抱歉),但是如果您担心可移植性,那么您可能还担心正确性-因此int main而不是void main
Stuart Golodetz

@Stuart-固定。应该在前一段时间做的。
J. Polfer 2011年

4
@ J.Polfer:return 0但这不是必须的,只是噪音!
Lightness Races in Orbit

Answers:


105

一种方法是发出中断信号:

#include <csignal>

// Generate an interrupt
std::raise(SIGINT);

在C中:

#include <signal.h>
raise(SIGINT);

更新MSDN声明 Windows并不真正支持SIGINT,因此,如果考虑到可移植性,最好使用SIGABRT


是的,这应该可以跨操作系统/编译器/调试器使用。
HAVARD小号

1
我不了解其他调试器,但gdb在信号处理方面相当灵活。
卡斯卡贝尔

4
我们发现在某些大学中SIGTRAP更好
JBRWilkinson 2012年

1
在Windows MSVC中,可以使用__debug_break,DebugBreak或_asm {int 3}。
费尔南多·冈萨雷斯·桑切斯2015年

2
@FernandoGonzalezSanchez:实际上,函数名称是__debugbreak()and NOT __debug_break(),正如您在此处
Morix Dev

27

在我从事的项目中,我们这样做:

raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */

(在我们的案例中,我们希望如果这种情况在调试器之外发生而导致严重崩溃,并在可能的情况下生成崩溃报告。这就是我们使用SIGABRT的原因。在Windows,Mac和Linux上可移植地进行此操作经历了几次尝试。最后我们做了几次尝试#ifdefs,在这里有帮助的评论:http : //hg.mozilla.org/mozilla-central/file/98fa9c0cff7a/js/src/jsutil.cpp#l66。)


2
像往常一样,窗户看起来不像其他窗户:)
mathk 2011年

是否可以发出“信号0”以在暂停状态下继续编写程序?从这点开始,能够使用'n'或's'而不发出'c'很好。
杰森·多塞特

2
@JasonDoucette如果您真的只是想让程序暂停,则可能要breakpoint()在程序中添加一个函数(它可以为空或仅包含一个print语句)并添加break breakpoint到中~/.gdbinit
杰森·奥伦多夫

26

通过查看这里,我发现了以下方式:

void main(int argc, char** argv)
{
    asm("int $3");
    int a = 3;
    a++;  //  In gdb> print a;  expect result to be 3
}

对我来说,这似乎有点荒谬。而且我认为这仅适用于x86架构。


3
并且仅适用于支持AT&T汇编语法的编译器。特别是,Microsoft的编译器(cl.exe)不支持此语法,但使用其他语法。
哈佛小号

问题是关于linux的,所以我想我们可以假设gcc语法适用于x86。
js。

顺便说一句-我确实在我的x86机器上尝试了上述方法,但它确实起作用了。我很好奇是否有更好的方法。看起来好像有。
J. Polfer

2
我在Windows上使用mingw,所以其他建议对我没有帮助。引发SIGINT信号只是终止应用程序,在mingw标头中未定义SIGTRAP ...使用int指令实际上发送SIGTRAP,并且gdb在适当的行上很好地中断了。
2014年

在Linux中,int 3引发SIGTRAP。
Ciro Santilli郝海东冠状病六四事件法轮功

11

__asm__("int $3"); 应该管用:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    __asm__("int $3");
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}

1
我喜欢#define这个,所以我不必记住语法。assert()由于停止了debiugger,让我检查所有变量和堆栈,因此我在整个代码中都花了点时间,有时甚至代替。而且,当然,就像断言一样,我不必为生产代码删除它
Mawg说,请恢复莫妮卡(Monica)2016年

有趣的是,当“ Linux”和“ GDB”的问题约束在不依靠汇编的情况下提供了许多选择时,它有10个异议。如果没有其他问题,出于可移植性的考虑,这应该永远是最后的手段。请查看其他一些答案。
Benjamin Crawford Ctrl-Alt-Tut


1

在OS X上,您可以调用std::abort()(在Linux上可能是相同的)


哪个图书馆?
Alex

这是标准C ++库的一部分,并且是存在C ++ 11兼容编译器的跨平台版本。但是,这会引发SIGABRT,在这种情况下,这实际上并不是一个适当的信号。
本杰明·克劳福德Ctrl-Alt-Tut
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.