Boost 中的 stacktrace 库提供了堆栈跟踪功能。堆栈跟踪又分了好几个子模块,其中最常用的两个模块是:
模块 | 作用 |
basic | 使用编译器的功能提供最基本的堆栈跟踪功能 |
addr2line | 使用 addr2line 将函数地址翻译成函数名 |
boost 使用 addr2line 的方式是 fork 子进程,然后在子进程中翻译函数地址。这会导致创建很多子进程。 |
要使用这两个模块,对 CMake 的方法为:
target_link_libraries(project PRIVATE Boost::stacktrace_basic Boost::stacktrace_addr2line)
target_compile_definitions(project PRIVATE BOOST_STACKTRACE_USE_ADDR2LINE)
打印堆栈
打印堆栈是最简单的使用方式,具体而言,调用:
std::cerr.clear();
std::cerr << boost::stacktrace::stacktrace() << std::endl;
导出堆栈
当程序发生崩溃时,打印堆栈的方式可能无法正常使用。更安全的方式是:
当程序崩溃时将堆栈信息保存到文件中
下次启动时读取堆栈信息
std::string kDumpFilePath = "./backtrace.dump";
void setup_backtrace() {
::signal(SIGABRT, handle_signal);
::signal(SIGSEGV, handle_signal);
}
void handle_signal(int signum) {
::signal(signum, SIG_DFL);
boost::stacktrace::safe_dump_to(kDumpFilePath.c_str());
std::cerr << boost::stacktrace::stacktrace() << std::endl;
::raise(SIGABRT);
}
void print_and_delete_dump_file() {
if(!boost::filesystem::exists(kDumpFilePath)) return;
std::ifstream ifs(kDumpFilePath);
auto st = boost::stacktrace::stacktrace::from_dump(ifs);
spdlog::info("上一次崩溃信息:");
std::cerr.clear();
std::cerr << st << std::endl;
ifs.close();
fflush(stderr);
boost::filesystem::remove(kDumpFilePath);
}