我试图看看SIGSEGV信号处理程序是否有助于处理未处理的C ++异常,我试验了它:
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
void *array[10];
size_t size = backtrace(array, 10);
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
int main()
{
signal(SIGSEGV, handler);
throw 1;
}
$ g ++ -g h.cpp -rdynamic&amp;&amp; ./a.out
在抛出&#39; int&#39;的实例后终止调用 中止(核心转储)
好吧,程序没有像我预期的那样打印崩溃调用堆栈返回跟踪。我的问题是:
只要它终止,它是否会通过SIGSEGV之类的任何信号? 是否有系统调用或posix api可以捕获甚至C ++异常并打印掉调用堆栈?
谢谢!
答案 0 :(得分:2)
您可以使用std::set_terminate安装终止处理程序 - 然后将针对未处理的异常调用已安装的处理程序。没有强有力的保证,但很有可能导致调用终止处理程序的abort
的调用发生在抛出异常的堆栈顶部,因此您仍然可以收集回溯。 / p>
此外,您可以为SIGABRT安装一个处理程序,它也可以运行:
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
void handler(int sig, siginfo_t*, void*) {
void *array[10];
size_t size = backtrace(array, 10);
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
void terminate_handler()
{
}
int main()
{
struct sigaction new_sigaction, old_sigaction;
new_sigaction.sa_flags = SA_SIGINFO;
new_sigaction.sa_sigaction = handler;
sigaction(SIGABRT, &new_sigaction, &old_sigaction);
throw 1;
}
我个人更喜欢终止处理程序,因为在这种情况下你明确知道原因。如果调用了SIGABRT处理程序,则必须理解这是因为调用了未处理的异常abort()
还是通过其他方式发送了信号。
答案 1 :(得分:0)
来自here
如果在堆栈展开期间调用的任何函数,在异常对象初始化之后和异常处理程序启动之前,异常退出,则会调用
std::terminate
。
简而言之,它表示如果未捕获异常std::terminate
被调用。 与 SEG不同。 FAULT
您的程序没有捕获异常,因此调用了std::terminate
,但这不会产生 sigfault 行为。
答案 2 :(得分:-2)
我认为你需要做
raise(SIGSEGV)
如果你想要在你的处理程序中结束:
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
void *array[10];
size_t size = backtrace(array, 10);
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
int main()
{
signal(SIGSEGV, handler);
raise(SIGSEGV);
}