分段故障时的调用堆栈

问题描述 投票:0回答:1

我编写了这个(backtrace.hpp)以在我的程序像分段错误一样崩溃时显示调用堆栈。

#pragma once
#include <map>
#include <iostream>
#include <signal.h>
#include <sys/stat.h>
#include <execinfo.h>
#include <sys/types.h>
#include <unistd.h>

static const std::map<int, std::string> signals_map =
{
    {SIGSEGV, "SIGSEGV"},
    {SIGABRT, "SIGABRT"},
    {SIGINT, "SIGINT"},
    {SIGFPE, "SIGFPE"},
    {SIGILL, "SIGILL"},
    {SIGSYS, "SIGSYS"},
    {SIGBUS, "SIGBUS"},
    {SIGIOT, "SIGIOT"},
    {SIGTRAP, "SIGTRAP"},
};

class Backtrace
{
private:
    static void ExceptionHandler(int signum, siginfo_t* info, void* ctx){
        int nptrs;
        void *buffer[1024];
        char **strings;

        nptrs = backtrace(buffer, 1024);
        strings = backtrace_symbols(buffer, nptrs);
        if (strings == NULL) {
            exit(EXIT_FAILURE);
        }

        std::cout<<std::endl<<"****** Crash Backtrace signal: "<<signals_map.at(signum)<<"******"<<std::endl<<std::endl;
        for (int i = 2; i < nptrs; i++) {
            std::cout<<"     "<<strings[i]<<std::endl;
        }

        free(strings);
        signal(signum, SIG_DFL);
    }
public:
    Backtrace(){
        struct sigaction action;
        sigemptyset(&action.sa_mask);
        action.sa_sigaction = &ExceptionHandler;
        action.sa_flags = SA_SIGINFO;
        for (const auto& signals: signals_map)
        {
            if (0 > sigaction(signals.first, &action, NULL))
            {
                std::cout<<"sigaction failed:"<<signals.second<<std::endl;
            }
        }
    }
    ~Backtrace(){}
};

通常是有用的。但有时,我只是得到这样的信息: $ /bin/sh: 第 1 行: 6571 分段错误 没有回溯输出。 为什么会出现这种情况?

在我的代码中,我像这样使用 backtrace.hpp:

#inlcude "backtrace.hpp"
int main(){
    Backtrace b;
    ...
}
c++ segmentation-fault callstack backtrace
1个回答
0
投票

为什么会出现这种情况?

可以在信号处理程序中合法使用的函数非常少(async-signal-safe)。

malloc
free
并不安全,
backtrace_symbols()
调用
malloc()
,使用
std::cout
简直就是自找麻烦。

可以

相当可靠地打印堆栈跟踪,但这需要很多的小心(以及相当多很多代码),而且你根本不小心

© www.soinside.com 2019 - 2024. All rights reserved.