c++ - 为什么 SIGSEGV 的信号处理程序无法捕获我的 C++ 抛出异常?

标签 c++ linux exception signals segmentation-fault

我试图看看 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/

相关文章:

c++ - boost::Program_options 如何在值中支持散列字符?

c++ - 数据结构设计模式

c++ - 如何使用 JSON 实现带有 POCO C++ 网络库的 REST API 服务器?

c++ - 如何在 Windows 窗体应用程序 vc++ 中导入 C 静态库

linux - linux中如何获取昨天和前天?

linux - 非 root 用户解压缩文件时是否可以保留 setgid 位?

java - Java 中使用内存映射文件的 IO 错误

c - 没有 sudo 的 SIGKILL init(PID=1)? Linux 中的错误?

javascript - 异常(exception)情况是固定位置的随机排列数组

java - 你如何阻止 Spring 吞噬异常?