我使用GCC编译器在Linux上工作。当我的c++程序崩溃时,我希望它自动生成一个堆栈跟踪。

我的程序由许多不同的用户运行,它也可以在Linux、Windows和Macintosh上运行(所有版本都使用gcc编译)。

我希望我的程序能够在崩溃时生成堆栈跟踪,下次用户运行它时,它会问他们是否可以将堆栈跟踪发送给我,这样我就可以跟踪到问题。我可以处理发送信息给我,但我不知道如何生成跟踪字符串。什么好主意吗?


当前回答

它看起来就像在最后一个c++增强版本中出现的库提供了你想要的东西,可能代码会是多平台的。 它是boost::stacktrace,你可以像在boost sample中那样使用:

#include <filesystem>
#include <sstream>
#include <fstream>
#include <signal.h>     // ::signal, ::raise
#include <boost/stacktrace.hpp>

const char* backtraceFileName = "./backtraceFile.dump";

void signalHandler(int)
{
    ::signal(SIGSEGV, SIG_DFL);
    ::signal(SIGABRT, SIG_DFL);
    boost::stacktrace::safe_dump_to(backtraceFileName);
    ::raise(SIGABRT);
}

void sendReport()
{
    if (std::filesystem::exists(backtraceFileName))
    {
        std::ifstream file(backtraceFileName);

        auto st = boost::stacktrace::stacktrace::from_dump(file);
        std::ostringstream backtraceStream;
        backtraceStream << st << std::endl;

        // sending the code from st

        file.close();
        std::filesystem::remove(backtraceFileName);
    }
}

int main()
{
    ::signal(SIGSEGV, signalHandler);
    ::signal(SIGABRT, signalHandler);

    sendReport();
    // ... rest of code
}

在Linux中编译上面的代码:

g++ --std=c++17 file.cpp -lstdc++fs -lboost_stacktrace_backtrace -ldl -lbacktrace

从boost文档复制的反向跟踪示例:

0# bar(int) at /path/to/source/file.cpp:70
1# bar(int) at /path/to/source/file.cpp:70
2# bar(int) at /path/to/source/file.cpp:70
3# bar(int) at /path/to/source/file.cpp:70
4# main at /path/to/main.cpp:93
5# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
6# _start

其他回答

城里的新国王来了 https://github.com/bombela/backward-cpp

在代码中放置1个头文件,安装1个库。

我个人使用这个函数来调用它

#include "backward.hpp"
void stacker() {

using namespace backward;
StackTrace st;


st.load_here(99); //Limit the number of trace depth to 99
st.skip_n_firsts(3);//This will skip some backward internal function from the trace

Printer p;
p.snippet = true;
p.object = true;
p.color = true;
p.address = true;
p.print(st, stderr);
}

您没有指定您的操作系统,因此这个问题很难回答。如果你使用的是基于gnu libc的系统,你可以使用libc函数backtrace()。

GCC还有两个内置组件可以帮助你,但它们可能也可能不能在你的架构上完全实现,它们是__builtin_frame_address和__builtin_return_address。两者都需要一个即时整数级别(这里的即时是指它不能是一个变量)。如果给定级别的__builtin_frame_address非零,那么获取同一级别的返回地址应该是安全的。

ulimit -c unlimited

是一个系统变量,它将允许在应用程序崩溃后创建一个核心转储。在这种情况下是无限的。在同一目录中查找一个名为core的文件。确保在编译代码时启用了调试信息!

问候

一些版本的libc包含处理堆栈跟踪的函数;你可能会用到它们:

http://www.gnu.org/software/libc/manual/html_node/Backtraces.html

我记得很久以前使用过libunwind来获取堆栈跟踪,但您的平台可能不支持它。

需要注意的是,一旦生成了核心文件,就需要使用gdb工具来查看它。为了让gdb理解你的核心文件,你必须告诉gcc用调试符号来检测二进制文件:要做到这一点,你需要使用-g标志进行编译:

$ g++ -g prog.cpp -o prog

然后,您可以设置“ulimit -c unlimited”来转储一个核心,或者只是在gdb中运行您的程序。我更喜欢第二种方法:

$ gdb ./prog
... gdb startup output ...
(gdb) run
... program runs and crashes ...
(gdb) where
... gdb outputs your stack trace ...

我希望这能有所帮助。