【问题标题】:On Linux, backtrace_symbols_fd function doesn't work as expected在 Linux 上,backtrace_symbols_fd 函数无法按预期工作
【发布时间】:2016-09-30 10:33:09
【问题描述】:

我参考了这个 Stack Overflow 问题来测试是否可以捕获和处理 SIGSEGV

How to automatically generate a stacktrace when my program crashes

文件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 a segmentation fault
}

我编译它们:

gcc -rdynamic -g h.cpp && ./a.out

结果:

分段错误(核心转储)

好吧,它并没有像我预期的那样打印出调用堆栈。我必须设置任何系统参数吗?

【问题讨论】:

  • 您没有在安装处理程序的主函数中注册信号处理程序使用signal(SIGSEGV, handler);

标签: c++ linux dynamic trace segmentation-fault


【解决方案1】:

有两个问题。

  1. SIGSEGV 处理程序未使用 sigaction() 注册。

  2. 在信号处理程序中,fprintf 被调用。 fprintf 不是可重入库函数,不能从信号处理程序中调用。特别是对于SIGSEGV,当整个堆可能已经从高轨道被核爆时,以及stderrs,内部文件缓冲区可能是一个冒烟的火山口。只有系统调用,如 write() 可以安全地从信号处理程序中调用。

【讨论】:

    【解决方案2】:

    改变 main 函数如下:

    int main()
    {
       signal(SIGSEGV, handler);  // Register handler
       int *foo = (int*)-1;  // Make a bad pointer
       printf("%d\n", *foo);  // Causes a segmentation fault
    }
    

    【讨论】:

    • signal() 已过时。所有新代码都应使用sigaction()
    猜你喜欢
    • 2018-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 2012-07-04
    相关资源
    最近更新 更多