我提到这个网络线程来测试是否可以捕获和处理SIGSEGV:
How to generate a stacktrace when my gcc C++ app crashes
$ cat h.cpp
#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);
// print out all the frames to stderr
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
exit(1);
}
int main()
{
int *foo = (int*)-1; // make a bad pointer
printf("%d\n", *foo); // causes segfault
}
我编译它们:
$ gcc -rdynamic -g h.cpp && ./a.out
$ Segmentation fault(core dump)
好吧它没有像我预期的那样打印掉调用堆栈。我是否必须设置任何系统参数?
答案 0 :(得分:1)
更改主要功能如下
int main()
{
signal(SIGSEGV, handler); // register handler
int *foo = (int*)-1; // make a bad pointer
printf("%d\n", *foo); // causes segfault
}
答案 1 :(得分:1)
有两个问题。
SIGSEGV
处理程序未使用sigaction()
注册。
在信号处理程序中,调用fprintf
。 fprintf
不是可重入的库函数,无法从信号处理程序中调用它。特别是对于SIGSEGV
,当潜在地,整个堆已经从高轨道和stderr
进行核心时,内部文件缓冲区可能是一个吸烟陨石坑。只能从信号处理程序中安全地调用write()
等系统调用。