我试图看看 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 && ./a.out
terminate called after throwing an instance of 'int' Aborted (Core dump)
嗯,程序没有按照我的预期打印崩溃调用堆栈回溯。我的问题是:
只要它终止,它是否会发出任何信号,例如 SIGSEGV? 是否有系统调用或 posix api 甚至可以捕获 C++ 异常并打印出调用堆栈?
谢谢!
最佳答案
您可以使用 std::set_terminate 安装终止处理程序- 然后将针对未处理的异常调用已安装的处理程序。没有强有力的保证,但很有可能导致调用终止处理程序的 abort
调用发生在引发异常的堆栈顶部,因此您仍然可以收集回溯。
此外,您还可以安装 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() 或信号是通过其他方式发送的。
关于c++ - 为什么 SIGSEGV 的信号处理程序无法捕获我的 C++ 抛出异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39790056/