2015-04-04 59 views
1

我的问题是:用C++覆盖崩溃

有没有办法在程序发生崩溃时调用函数或做其他工作。

具体而言,我目前正在使用的代码在非常大的输入上出现“段错误”。这意味着我正在访问一些不可用的\未分配内存部分。显示每一步都太难理解了,所以我想要检测什么时候跨越了我的界限。

那么这怎么可能呢?

+1

为什么不按顺序运行下的valgrind代码中查找和修复bug( s)? – 2015-04-04 09:53:30

+2

“我想要检测什么时候越过我的界限”与“在发生崩溃时调用函数或做其他工作”无关。使用调试器对前者有好处。从C++的角度来看,后者是一般未定义行为机制的功能,在这种制度下,C++标准没有任何保证。不过,对于正常的终止,包括未捕获的异常,你有'std :: terminate'。 – 2015-04-04 10:13:52

+0

是的(我看到它是一种unix) - 编译时启用了调试(cc -g ...),然后使用gdb:gdb --args ./program 运行,然后运行 – 2015-04-04 13:30:04

回答

1

它是操作系统和具体实现。实际上也取决于编译器和优化标志。

很可能,你已经打了一些undefined behavior

也许valgrind应该是一个非常有用的工具。

如果在Linux上,阅读core(5) & proc(5) & signal(7)。您可能会在系统范围内设置您的/proc/sys/kernel/core_pattern伪文件来启动核心转储中的某个外部程序或脚本(可能启动一个调试器)。

你甚至可以在处理器和操作系统,系统特定的方式处理SIGSEGV信号。但我不建议这样做。见this & that 答案更多。

在Linux上,系统调用(在syscalls(2)上市)几乎可以将信号处理程序内调用的唯一功能(更确切地说,它是在signal(7)而已提到异步信号安全功能)。但是很多的库函数(包括malloc & printffprintfdlopen等等)都是内部信号处理程序被禁止。

1

如果您编译与调试符号代码,你应该能够在碰撞发生时要么加载一个核心文件到您的调试器和/或附加一个调试器。

通常情况下,你可以告诉崩溃的位置发生了什么。你解除引用空指针吗?你解除了一个无效指针吗?第二个比第一个更难调试(通常意味着内存损坏)。一个用于内存损坏的有用工具,尤其是在错误是可重复的情况下使用,就是放置“观察点”,只要某个特定的内存位置(即导致崩溃的指针)发生改变,就会导致调试器暂停。这可以让你看到什么改写了你的指针。

1

你确实需要一个调试器。但是,为了回答一个问题,原为未来的搜索:

是,在UNIX你可以只处理与通常的信号处理程序的SEGV信号。 SIGSEGV的编号为13.有关如何处理信号,请参阅this

请注意系统对信号处理程序 (例如系统调用被禁止,包括IO)可以做的限制有限制。 此外,如果访问您的程序数据等待它可能已损坏。你的程序会在信号处理程序之后继续工作,但它很可能会很快进入另一个错误。

我不会电子书籍这样做在生产代码,但我觉得这个功能是“Unix的”提够的SO

+0

syscalls被允许(在Linux上)信号处理程序。但是很多功能都被禁止。看到我的答案。 – 2015-04-08 17:36:32