当前位置: 首页 > news >正文

崩溃信息追溯——backward-cpp

  在日常的软件开发过程中,总是避免不了出现程序运行中突然的崩溃,如果已知一个必然崩溃的现象且可复现的话,这种bug还方便排查,加打印或者用gdb运行程序崩溃后可以追溯栈信息。
  但如果是一个偶现的崩溃,这就比较棘手了,需要我们在程序开发时就增加一些机制,帮助我们更高效地定位程序错误。

目录

  • 1.关于backward-cpp
  • 2.依赖backward库
    • 2.1 C++版本
      • 安装方式
      • CMake集成
    • 2.2 ROS2版本
  • 3.在代码中启用backward-cpp和日志功能
    • 3.1 增加头文件
    • 3.2 安装信号处理器
    • 3.3 处理崩溃信号的函数
    • 3.4 重新编译
    • 四:运行测试

1.关于backward-cpp

源码:

  • C++版本:https://github.com/bombela/backward-cpp
  • ROS2版本:https://github.com/pal-robotics/backward_ros
    https://index.ros.org/p/backward_ros

两者区别:

  • C++版本与ROS2版本功能一样;
  • ROS2版本在C++版本的基础上修改了CMakeLists,其他节点依赖backward库时,可以使用 find_package(backward_ros REQUIRED) 依赖,只是依赖更方便。

注意:

  • backward 库只能捕捉 一些特定类型的崩溃,主要是:程序崩溃导致信号触发:SIGSEGV(段错误,比如野指针)SIGABRT(程序调用 abort())SIGFPE(数学错误,比如除以零)SIGILL(非法指令)SIGBUS(总线错误)
  • 不能捕捉的情况:
    1.普通 C++ 异常(如 std::runtime_error)
    2.第三方库(如 toml库)里本身处理的异常

2.依赖backward库

2.1 C++版本

安装方式

  • header only 模式:只需将 backward.hpp 放入项目中即可使用基本功能
  • 完整功能模式:添加 backward.cpp 到项目中,可实现自动捕获致命错误并打印栈跟踪

CMake集成

  • 作为子目录添加到项目
  • 让backward-cpp参与编译
    target_link_libraries(${PROJECT_NAME} ...) 里添加:
target_link_libraries(${PROJECT_NAME}backwarddw      # backward依赖dw库,不添加dw库可能会编译报错
)

2.2 ROS2版本

  • 在CMakeLists.txt中添加backward_ros依赖
    在CMakeLists.txt文件中添加:
find_package(backward_ros REQUIRED)
  • 在package.xml文件中添加
<depend>backward_ros</depend>
  • 可执行文件依赖backeard_ros
target_link_libraries(${PROJECT_NAME}backward_ros
)

3.在代码中启用backward-cpp和日志功能

3.1 增加头文件

#include <backward.hpp>

这是 backward-cpp 的主入口,它会自动包含 StackTracePrinter 这两个核心类。

3.2 安装信号处理器

int main(int argc, char **argv)
{std::string log_file      = std::filesystem::current_path().string() + "/bjx_elevator_driver.INFO";std::string agvc_log_path = "/mnt/agvc/log";if (std::filesystem::exists(agvc_log_path)) {std::string log_path = agvc_log_path + "/bjx_elevator_driver";if (!std::filesystem::exists(log_path)) {std::filesystem::create_directory(log_path);}log_file = log_path + "/bjx_elevator_driver.INFO";}google::InitGoogleLogging(argv[0]); // 设置GLOG参数FLAGS_max_log_size     = 100;       // 最大日志大小(MB), 如果设置为0将默认为1FLAGS_alsologtostderr  = true;      // 同时输出到文件FLAGS_colorlogtostderr = true;      // 显示颜色FLAGS_logbufsecs       = 0;         // 设置日志滚动时间间隔为的秒数FLAGS_v                = 0;         // 设置日志输出等级google::SetLogDestination(google::INFO, log_file.c_str());google::EnableLogCleaner(std::chrono::hours(24 * 7)); // 7天清理一次日志LOG(INFO) << "log file: " << log_file;signal(SIGSEGV, signal_handler); // 监听 SIGSEGV 崩溃信号LOG(INFO) << "程序启动!";// 触发崩溃int* ptr = nullptr;*ptr = 42;return 0;
}
signal(SIGSEGV, signal_handler);

这行代码注册了一个信号处理函数 signal_handler,放在需要检测的程序或节点中,当程序遇到 SIGSEGV(段错误)时就会跳进这个函数。也就是说,当程序崩了,交给此函数处理,而不是让程序直接终止。

3.3 处理崩溃信号的函数

void signal_handler(int signum) {backward::StackTrace st;st.load_here(32);// 使用 Printer 格式化堆栈信息backward::Printer p;std::ostringstream oss;p.print(st, oss);// 记录到 glogLOG(ERROR) << "程序崩溃!信号: " << signum;LOG(ERROR) << "崩溃堆栈信息:\n" << oss.str();exit(1);
}
  • backward::StackTrace 是一个类,用于保存当前调用栈的快照。
  • load_here(32) 会捕捉当前线程最多 32 层的调用栈信息。
  • Printer 是用来格式化并打印 StackTrace 的工具类。
  • 它可以打印到 std::coutstd::cerrstd::ostringstream 等。
  • 打印出来的内容会包括:哪个函数、哪个源码文件、哪一行调用的
  • 使用 glog 来将堆栈信息作为错误日志输出,这样你不仅能看到程序崩溃,还能知道在哪一行出了问题。

3.4 重新编译

rm -rf build
mkdir build && cd build
cmake ..
make -j

四:运行测试

运行可执行文件

如果崩溃,你会看到:

I20250403 13:28:27.121705 134548333981312 jsonrpc_client_test.cpp:127] 程序启动!
E20250403 13:28:27.210820 134548333981312 jsonrpc_client_test.cpp:96] 程序崩溃!信号: 11
E20250403 13:28:27.211076 134548333981312 jsonrpc_client_test.cpp:97] 崩溃堆栈信息:
Stack trace (most recent call last):
#8    Object "", at 0xffffffffffffffff, in 
#7    Object "/home/lik/bjx_elevator_driver/build/jsonrpc_client_test", at 0x5630b994b1c4, in _start
#6    Source "../csu/libc-start.c", line 392, in __libc_start_main_impl
#5    Source "../sysdeps/nptl/libc_start_call_main.h", line 58, in __libc_start_call_main
#4    Source "/home/lik/bjx_elevator_driver/test/jsonrpc_client_test.cpp", line 131, in main129:     // 触发崩溃130:     int* ptr = nullptr;> 131:     *ptr = 42;132: 133:     return 0;134: }
#3    Object "/usr/lib/x86_64-linux-gnu/libc.so.6", at 0x7a5ef944251f, in 
#2    Source "/home/lik/bjx_elevator_driver/test/jsonrpc_client_test.cpp", line 88, in signal_handler85: // 处理崩溃信号的函数86: void signal_handler(int signum) {87:     backward::StackTrace st;>  88:     st.load_here(32);89: 90:     // 使用 Printer 格式化堆栈信息91:     backward::Printer p;
#1    Source "/home/lik/.cache/CPM/backward-cpp/backward.hpp", line 879, in load_here876:       return 0;877:     }878:     _stacktrace.resize(depth);> 879:     size_t trace_cnt = details::unwind(callback(*this), depth);880:     _stacktrace.resize(trace_cnt);881:     skip_n_firsts(0);882:     return size();
#0    Source "/home/lik/.cache/CPM/backward-cpp/backward.hpp", line 861, in unwind<backward::StackTraceImpl<backward::system_tag::linux_tag>::callback>859: template <typename F> size_t unwind(F f, size_t depth) {860:   Unwinder<F> unwinder;> 861:   return unwinder(f, depth);862: }863: 864: } // namespace details
http://www.dtcms.com/a/508445.html

相关文章:

  • 怎么找网站帮我做推广wordpress加入下载标签
  • 深度学习实验二 简单神经网络模型构建
  • IP 汇总名单
  • 同城购物网站建设成本有人上相亲网站做传销燕窝
  • P7073 [CSP-J2020] 表达式
  • 昆山住房与城乡建设局网站成都市成华区建设局官方网站
  • 2025 年六款 AI 视频转文字工具实测分析:功能与场景适配对比
  • 如何做微信网站建设紫色的网站
  • dify 源码分析(六)ratelimiter
  • 阜阳网站开发招聘网站维护电话
  • 傻瓜式做网站哪个软件好网站搭建模板
  • 做国外家具贸易的网站重庆网站建设mlfart
  • 绵阳网站建设公司广州引流推广公司
  • 容桂做外贸网站海口分类信息网站
  • 宁波高端模板建站搭建网站开发网站环境
  • 青岛seo网站排名徐州免费网站建设
  • Redis Stream相比阻塞列表和发布订阅有哪些优势?适合什么场景?
  • 企业每年向工商网站做申报如何把网站提交给百度
  • seo网站模板做网站推广什么好
  • 正则表达式:用Python Re模块驯服文本数据的艺术
  • 使用 Docker 容器测试端口开放性
  • 后端常用注解
  • Spring 的bean是安全的吗
  • 网站建设优化现状图表网站开发结构文档
  • 【Git】【TortoiseGit】TortoiseGit安装与基础使用
  • 灵巧手——DexMV
  • 营销型外贸网站建设软件怎么引流怎么推广自己的产品
  • 联兴建设官方网站wordpress增加幻灯片
  • HarmonyOS多媒体开发:自定义相机与音频播放器实战
  • HYPE分布式水文模型建模方法与案例分析