简体   繁体   English

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

[英]Why signal handler for SIGSEGV doesn't catch my C++ throw exception?

I was trying to see if SIGSEGV signal hander could help to deal with unhandled exception of C++, I experiment it:我试图看看 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 $ g++ -g h.cpp -rdynamic && ./a.out

terminate called after throwing an instance of 'int' Aborted (Core dump)抛出“int”的实例后调用终止中止(核心转储)

Well, the program doesn't print crash call stack back trace as I expected.好吧,该程序没有像我预期的那样打印崩溃调用堆栈回溯。 My question is:我的问题是:

As long as it terminates, does it through out any signals like SIGSEGV?只要它终止,它是否会通过像 SIGSEGV 这样的任何信号? Is there a system call or posix api that could catch even C++ exceptions and prints out the call stack?是否有系统调用或 posix api 甚至可以捕获 C++ 异常并打印出调用堆栈?

Thanks!谢谢!

You can install a termination handler with std::set_terminate - the installed handler will then be invoked for unhandled exception.您可以使用std::set_terminate安装终止处理程序 - 然后将调用已安装的处理程序以处理未处理的异常。 There is no strong guarantee, but there is a great chance that the invocation of abort that causes invocation of the termination handler is occurring on the top of the stack that threw the exception and thus you can still collect a backtrace.没有强有力的保证,但是很有可能导致终止处理程序调用的abort调用发生在引发异常的堆栈顶部,因此您仍然可以收集回溯。

Also, you can install a handler for SIGABRT, that will work as well:此外,您可以为 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;
}

I'd personally prefer the termination handler, since in that case you explicitly know the cause.我个人更喜欢终止处理程序,因为在这种情况下,您明确知道原因。 If the SIGABRT handler is invoked you must understand if this is because an unhandled exception invoked abort() or the signal was sent by other means.如果调用了 SIGABRT 处理程序,您必须了解这是因为未处理的异常调用了abort()还是通过其他方式发送了信号。

I think you need to do我认为你需要做

raise(SIGSEGV)

if you want to end up in your handler:如果你想在你的处理程序中结束:

#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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM