为什么SIGSEGV的信号处理程序没有捕获我的C ++抛出异常?

时间:2016-09-30 11:05:18

标签: c++ linux exception signals sigsegv

我试图看看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 ++异常并打印掉调用堆栈?

谢谢!

3 个答案:

答案 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);
}