优雅地打印堆栈跟踪信息——Backward-cpp

news2024/11/18 11:37:46

优雅地打印堆栈跟踪信息——Backward-cpp

文章目录

  • 优雅地打印堆栈跟踪信息——Backward-cpp
  • 介绍
    • 编译Backward-cpp
        • 下载源码
        • 文件结构
        • 安装第三方库
        • 编译
        • 测试
    • 集成Backward-cpp
      • 测试代码
    • 安装
        • backward.hpp
        • backward.cpp
    • 使用方法
      • g++直接编译
      • CMake
        • backward.hpp backward.cpp加入程序编译
        • backward-cpp作为子目录编译
        • 使用`FetchContent()`:
        • 修改CMAKE_MODULE_PATH
    • Reference
      • >>>>> 欢迎关注公众号【三戒纪元】 <<<<<

介绍

项目地址:backward-cpp

C/C++编程的同学经常会遇到程序出现段错误:

Segmentation fault (core dumped)

而 Backward 会将堆栈信息打印出来,帮助定位。有点像gdb时的backtrace

在这里插入图片描述

只有当源文件可访问时,它才能显示代码片段。

所有以管道“|”为前缀的“源”行和代码片段都是内联下一帧的帧。

项目源码本质上只有backward.hpp文件,集成到自己的程序中非常方便,如果加入backward.cpp文件一起编译,则自己代码中不需要调用Backward-cpp中的函数,非常方便。


编译Backward-cpp

下载源码

git clone https://github.com/bombela/backward-cpp.git

文件结构

主文件:

.
├── backward.cpp
└── backward.hpp

其中 backward.cpp是在调用backward.hpp文件:

#include "backward.hpp"

namespace backward {
	backward::SignalHandling sh;
} // namespace backward

测试文件:

.test
├── rectrace.cpp
├── select_signals.cpp
├── stacktrace.cpp
├── suicide.cpp
├── test.cpp
├── test.hpp
└── _test_main.cpp

安装第三方库

sudo apt-get install libdw-dev
sudo apt-get install binutils-dev
sudo apt-get install libdwarf-dev

编译

# cmake
(base) qiancj@qiancj-HP-ZBook-G8:~/codes/download/backward-cpp/build$ cmake ..
-- The CXX compiler identification is GNU 9.4.0
...
-- Found libdw: /usr/lib/x86_64-linux-gnu/libdw.so  
-- Found libbfd: /usr/lib/x86_64-linux-gnu/libbfd.so  
-- Found libdwarf: /usr/lib/x86_64-linux-gnu/libdwarf.so  
-- Found Backward: /home/qiancj/codes/download/backward-cpp  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/qiancj/codes/download/backward-cpp/build

# make
(base) qiancj@qiancj-HP-ZBook-G8:~/codes/download/backward-cpp/build$ make
Scanning dependencies of target backward_object
[  7%] Building CXX object CMakeFiles/backward_object.dir/backward.cpp.o
...
Scanning dependencies of target test_rectrace
[ 21%] Building CXX object CMakeFiles/test_rectrace.dir/test/rectrace.cpp.o
...
[ 85%] Linking CXX executable test_suicide
...
[ 92%] Building CXX object CMakeFiles/test_select_signals.dir/test/select_signals.cpp.o
[100%] Linking CXX executable test_select_signals
[100%] Built target test_select_signals

# 编译生成文件
(base) qiancj@qiancj-HP-ZBook-G8:~/codes/download/backward-cpp/build$ ls
CMakeCache.txt  cmake_install.cmake  libbackward.a  test_rectrace        test_stacktrace  test_test
CMakeFiles      CTestTestfile.cmake  Makefile       test_select_signals  test_suicide

测试

(base) qiancj@qiancj-HP-ZBook-G8:~/codes/download/backward-cpp/build$ ./test_stacktrace 
-- running test case: minitrace
Stack trace (most recent call last):
#9    Object "", at 0xffffffffffffffff, in 
#8    Object "/home/qiancj/codes/download/backward-cpp/build/test_stacktrace", at 0x55c82d46edad, in _start
#7    Source "../csu/libc-start.c", line 308, in __libc_start_main
#6    Source "/home/qiancj/codes/download/backward-cpp/test/_test_main.cpp", line 227, in main
        224:     }
        225: 
        226:     total_cnt += 1;
      > 227:     if (run_test(test)) {
        228:       printf("-- test case success: %s\n", test.name);
        229:       success_cnt += 1;
        230:     } else {
#5    Source "/home/qiancj/codes/download/backward-cpp/test/_test_main.cpp", line 140, in run_test
        138:   pid_t child_pid = fork();
        139:   if (child_pid == 0) {
      > 140:     exit(static_cast<int>(test.run()));
        141:   }
        142:   if (child_pid == -1) {
        143:     error(EXIT_FAILURE, 0, "unable to fork");
#4    Source "/home/qiancj/codes/download/backward-cpp/test/test.hpp", line 92, in run
         90:   TestStatus run() {
         91:     try {
      >  92:       do_test();
         93:       return SUCCESS;
         94:     } catch (const AssertFailedError &e) {
         95:       printf("!! %s\n", e.what());
#3    Source "/home/qiancj/codes/download/backward-cpp/test/stacktrace.cpp", line 37, in do_test
         34:   Printer printer;
         35: 
         36:   StackTrace st;
      >  37:   collect_trace(st);
         38: 
         39:   printer.print(st, std::cout);
         40: }
#2    Source "/home/qiancj/codes/download/backward-cpp/test/stacktrace.cpp", line 31, in collect_trace
         29: using namespace backward;
         30: 
      >  31: void collect_trace(StackTrace &st) { st.load_here(); }
         32: 
         33: TEST(minitrace) {
         34:   Printer printer;
#1    Source "/home/qiancj/codes/download/backward-cpp/backward.hpp", line 879, in load_here
        876:       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/qiancj/codes/download/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
-- test case success: minitrace
-- running test case: smalltrace
Stack trace (most recent call last):
#12   Object "", at 0xffffffffffffffff, in 
#11   Object "/home/qiancj/codes/download/backward-cpp/build/test_stacktrace", at 0x55c82d46edad, in _start
#10   Source "../csu/libc-start.c", line 308, in __libc_start_main
#9    Source "/home/qiancj/codes/download/backward-cpp/test/_test_main.cpp", line 227, in main
        224:     }
        225: 
        226:     total_cnt += 1;
      > 227:     if (run_test(test)) {
        228:       printf("-- test case success: %s\n", test.name);
        229:       success_cnt += 1;
        230:     } else {
#8    Source "/home/qiancj/codes/download/backward-cpp/test/_test_main.cpp", line 140, in run_test
        138:   pid_t child_pid = fork();
        139:   if (child_pid == 0) {
      > 140:     exit(static_cast<int>(test.run()));
        141:   }
        142:   if (child_pid == -1) {
        143:     error(EXIT_FAILURE, 0, "unable to fork");
#7    Source "/home/qiancj/codes/download/backward-cpp/test/test.hpp", line 92, in run
         90:   TestStatus run() {
         91:     try {
      >  92:       do_test();
         93:       return SUCCESS;
         94:     } catch (const AssertFailedError &e) {
         95:       printf("!! %s\n", e.what());
#6    Source "/home/qiancj/codes/download/backward-cpp/test/stacktrace.cpp", line 54, in do_test
         51:   Printer printer;
         52: 
         53:   StackTrace st;
      >  54:   a(st);
         55: 
         56:   printer.print(st, std::cout);
         57: }
#5    Source "/home/qiancj/codes/download/backward-cpp/test/stacktrace.cpp", line 48, in a
         46: void b(StackTrace &st) { return c(st); }
         47: 
      >  48: NOINLINE void a(StackTrace &st) { return b(st); }
         49: 
         50: TEST(smalltrace) {
         51:   Printer printer;
#4    Source "/home/qiancj/codes/download/backward-cpp/test/stacktrace.cpp", line 46, in b
         44: void c(StackTrace &st) { return d(st); }
         45: 
      >  46: void b(StackTrace &st) { return c(st); }
         47: 
         48: NOINLINE void a(StackTrace &st) { return b(st); }
#3    Source "/home/qiancj/codes/download/backward-cpp/test/stacktrace.cpp", line 44, in c
         42: void d(StackTrace &st) { st.load_here(); }
         43: 
      >  44: void c(StackTrace &st) { return d(st); }
         45: 
         46: void b(StackTrace &st) { return c(st); }
#2    Source "/home/qiancj/codes/download/backward-cpp/test/stacktrace.cpp", line 42, in d
         39:   printer.print(st, std::cout);
         40: }
         41: 
      >  42: void d(StackTrace &st) { st.load_here(); }
         43: 
         44: void c(StackTrace &st) { return d(st); }
#1    Source "/home/qiancj/codes/download/backward-cpp/backward.hpp", line 879, in load_here
        876:       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/qiancj/codes/download/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
-- test case success: smalltrace
-- tests passing: 2/2 (100%)

集成Backward-cpp

测试代码

#include<stdio.h>
#include<stdlib.h>

int main(){
    char *c = "hello world";
    c[1] = 'H';
}

安装

backward.hpp

Backward 仅是一个头文件库。

安装 Backward 很容易,只需将“backward.hpp”的副本与其他源文件一起放入C++项目中即可。你也可以使用 git submodule或任何其他最适合你环境的方式,只要你能包含 ‘backward.hpp’。

backward.cpp

如果您希望 Backward 自动打印最常见的致命错误(段错误、中止、未处理的异常等)的堆栈跟踪,只需将“backward.cpp”的副本添加到项目中,一起编译即可。

使用方法

g++直接编译

源码中添加

#include<stdio.h>
#include<stdlib.h>
#define BACKWARD_HAS_DW 1
#include "backward.hpp"
namespace backward{
    backward::SignalHandling sh;
}

int main(){
    char *c = "hello world";
    c[1] = 'H';
}

编译程序

g++ -o randy test_backward.cpp -g -ldw
    
test_backward.cpp: In function ‘int main():
test_backward.cpp:10:15: warning: ISO C++ forbids converting a string constant to ‘char*[-Wwrite-strings]
   10 |     char *c = "hello world";
      |               ^~~~~~~~~~~~~

运行程序

$ ./randy 
Stack trace (most recent call last):
#3    Object "", at 0xffffffffffffffff, in 
#2    Object "/home/qiancj/codes/test/backward/randy", at 0x562025c8eecd, in _start
#1    Source "../csu/libc-start.c", line 308, in __libc_start_main [0x7f5ff0c6d082]
#0    Source "/home/qiancj/codes/test/backward/test_backward.cpp", line 11, in main [0x562025c8efa4]
          9: int main(){
         10:     char *c = "hello world";
      >  11:     c[1] = 'H';
         12: }
Segmentation fault (Invalid permissions for mapped object [0x562025c9d0e8])
Segmentation fault (core dumped)

CMake

backward.hpp backward.cpp加入程序编译

文件结构

.
├── backward.cpp
├── backward.hpp
├── CMakeLists.txt
└── test_backward.cpp

CMakeLists.txt

cmake_minimum_required ( VERSION 2.6 FATAL_ERROR)  
project(randy)                                 
add_definitions(-std=c++14 -ofast)

set(CMAKE_CXX_FLAGS "-O0 -g -Wall -ggdb")

include_directories(${PROJECT_NAME} .)

add_executable(${PROJECT_NAME} test_backward.cpp backward.cpp)

运行结果

(base) qiancj@qiancj-HP-ZBook-G8:~/codes/test/backward/build$ ./randy 
Stack trace (most recent call last):
#3    Object "[0xffffffffffffffff]", at 0xffffffffffffffff, in 
#2    Object "./randy", at 0x55821e769b6d, in _start
#1    Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f2471945082, in __libc_start_main
#0    Object "./randy", at 0x55821e769c44, in main
Segmentation fault (Invalid permissions for mapped object [0x55821e776005])
Segmentation fault (core dumped)

backward-cpp作为子目录编译

文件结构

.
├── backward-cpp # Backward-cpp 源文件夹,作为项目子目录
├── backward.cpp
├── backward.hpp
├── CMakeLists.txt
└── test_backward.cpp

CMakeLists.txt 中需要包含

add_subdirectory(/path/to/backward-cpp)

# This will add backward.cpp to your target
add_executable(mytarget mysource.cpp ${BACKWARD_ENABLE})

# This will add libraries, definitions and include directories needed by backward
# by setting each property on the target.
add_backward(mytarget)

实际CMakeLists.txt :

cmake_minimum_required ( VERSION 2.6 FATAL_ERROR)  
project(randy)                                   

add_definitions(-std=c++14 -ofast)

add_subdirectory(./backward-cpp)

set(CMAKE_CXX_FLAGS "-g -Wall")

include_directories(${PROJECT_NAME} .)

add_executable(${PROJECT_NAME} test_backward.cpp ${BACKWARD_ENABLE})

add_backward(${PROJECT_NAME})

使用FetchContent():

如果使用的是最新版本的CMake,则可以通过FetchContent向后集成

include(FetchContent)

# Also requires one of: libbfd (gnu binutils), libdwarf, libdw (elfutils)
FetchContent_Declare(backward
        GIT_REPOSITORY https://github.com/bombela/backward-cpp
        GIT_TAG v1.6)
FetchContent_MakeAvailable(backward)

file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.cpp)
add_executable(example ${SOURCES} ${BACKWARD_ENABLE}) # Notice the "BACKWARD_ENABLE" here
add_backward(example)

这种做法不需要自己手动clone backward-cpp源码。

修改CMAKE_MODULE_PATH

在这种情况下,可以将Backward-cpp安装为子目录:

list(APPEND CMAKE_MODULE_PATH /path/to/backward-cpp)
find_package(Backward)

# This will add libraries, definitions and include directories needed by backward
# through an IMPORTED target.
target_link_libraries(mytarget PUBLIC Backward::Backward)

这等效于使用 add_subdirectory() 的方法,但它使用 cmake 导入的目标机制。

Reference

  • github backward-cpp

  • C程序集成Backward-cpp使用示例


>>>>> 欢迎关注公众号【三戒纪元】 <<<<<

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1011756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GRACE球谐数据滤波处理(利用matlab实现GRACE月水储量的二维傅里叶变化滤波)

GRACE的全球重力场产品以球谐系数&#xff08;SHCs&#xff09;的形式表现出明显的南北条带噪声问题&#xff0c;这种噪声被认为来源于它的极轨道、缺乏横向敏感性以及采样频率引起的混叠效应。 空间滤波器的例子包括各向同性高斯滤波器&#xff08;Wahr et al.&#xff0c;19…

GDB之保存已经设置的断点(十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

MQTT Paho Android 支持SSL/TLS(亲测有效)

MQTT Paho Android 支持SSL/TLS(亲测有效) 登录时支持ssl的交互 这是调测登录界面设计 代码中对ssl/tls的支持 使用MqttAndroidClient配置mqtt客户端请求时&#xff0c;不加密及加密方式连接存在以下几点差异&#xff1a; url及端口差异 val uri: String if (tlsConnect…

无涯教程-JavaScript - OR函数

描述 如果任何参数为TRUE,则OR函数返回TRUE&#xff1b;如果所有参数为FALSE,则返回FALSE。 语法 OR (logical1, [logical2], ...) 争论 Argument描述Required/Optionallogical1 您要测试的1到255个条件可以是TRUE或FALSE。 您要测试的1到255个条件可以是TRUE或FALSE。 Req…

大数据-玩转数据-oracel字符串分割转化为多列

一、建表 create table split_string_test(id integer primary key,test_string varchar2(500) );二、插入测试数据 insert into split_string_test values(1, 10,11,12,13,14,22); insert into split_string_test values(2, 22,23,24); insert into split_string_test valu…

MySQL5.7修改默认端口

1. 修改配置文件 首先打开MySQL的配置文件 my.ini&#xff0c;我的路径在 C:\ProgramData\MySQL\MySQL Server 5.7 &#xff0c;如何寻找自己的MySQL配置文件所在位置呢&#xff1f; 1.1 寻找配置文件 首先按下 wins &#xff0c;搜索 “服务” &#xff0c; 找到MySQL服务…

常驻巨噬细胞诱导的纤维化在胰腺炎性损伤和PDAC中具有不同的作用

介绍一篇2023年8月10日发表在Nature Immunology的文章 标题&#xff1a; Fibrosis induced by resident macrophages has divergent roles in pancreas inflammatory injury and PDAC 影响因子&#xff1a;30.5 DOI&#xff1a;https://doi.org/10.1038/s41590-023-01579-x …

对SPA单页面的理解

SPA单页面应用 SPA&#xff08;single-page application&#xff09;&#xff0c;翻译过来就是单页应用SPA是一种网络应用程序或网站的模型&#xff0c;它通过动态重写当前页面来与用户交互&#xff0c;这种方法避免了页面之间切换打断用户体验。 在单页应用中&#xff0c;所…

[移动通讯]【Carrier Aggregation-4】【LTE-4】

前言&#xff1a; 推荐两个在线工具 UECapabilityInformation Decoder: https://www.sqimway.com/ue_capa.php FGI Decoder: http://howltestuffworks.blogspot.com/2016/11/lte-feature-group-indicators-decoder.html 参考&#xff1a; 载波聚合&#xff08;CA&#xff09;…

webpack-cl明明已经安装了,但是还是会报未安装

解决办法&#xff1a;对当前项目目录进行安装 npm install webpack webpack-cli --save-dev

前端css实现统计圆环

文章目录 效果图 css的原理 左右两边分开制作&#xff0c;左右两边各有两层盒子&#xff0c;外层负责遮挡溢出的部分&#xff0c;里层旋转表示百分比 template部分 // 圆环的代码 <div class"row rel"><div class"left"><div id"lef…

U8用友ERP本地部署异地远程访问:内网端口映射外网方案

文章目录 前言1. 服务器本机安装U8并调试设置2. 用友U8借助cpolar实现企业远程办公2.1 在被控端电脑上&#xff0c;点击开始菜单栏&#xff0c;打开设置——系统2.2 找到远程桌面2.3 启用远程桌面 3. 安装cpolar内网穿透3.1 注册cpolar账号3.2 下载cpolar客户端 4. 获取远程桌面…

华为云创新中心黑湖科技:将智能制造进行到底

编辑&#xff1a;阿冒 设计&#xff1a;沐由 一如去年&#xff0c;第二届828 B2B企业节从8月28日-9月15日期间&#xff0c;再一次成为广大企业界关注的焦点。 当前&#xff0c;数字技术已经被广泛被融入到产品、服务与流程当中&#xff0c;用以转变客户的业务成果&#xff0c;以…

Nginx map 实现时间格式转换

哈喽大家好&#xff0c;我是咸鱼 最近我们需要把 Nginx 的日志接入到自研的日志采集平台上&#xff0c;但是这个平台只支持 JSON 格式&#xff0c;所以需要把 Nginx 日志格式改成 JSON 格式 例如下面这样的效果 刚开始在主配置文件 nginx.conf 中定义了一个名叫 json 的日志…

好用的电容笔有哪些推荐?apple pencil的平替笔推荐

很小伙伴会觉得越贵的电容笔就会越好用&#xff0c;但其实不是这样子的。我们要综合产品的性能和价格来购买。在电容笔领域中&#xff0c;性价比是很重要购买参数&#xff0c;今天我给大家推荐几款性价比高的平替电容笔&#xff0c;希望可以给你带来有益的参考。 1.西圣电容笔…

雅思学习总结

#【中秋征文】程序人生&#xff0c;中秋共享# 雅思小科普&#xff1a; 1. 什么是雅思考试&#xff1f; 雅思考试是由&#xff1a;英国文化协会、澳洲 IDP 教育集团、剑桥 大学考试委员会举办的英语水平测试。全称翻译成中文是&#xff1a; 国际英语语言测试系统。 2…

一招识别吞没和Marubozu,只需记住FPmarkets澳福这两点

在后台有很多投资者都在问FPmarkets澳福&#xff0c;吞没和Marubozu这两种形态的区别&#xff0c;今天这篇文章通过相似和不同来了解吞没和Marubozu这两种形态的区别。 共同点&#xff1a; 1. Marubozu和吞没都是烛台分析中的反转形态。 2.这两种模式&#xff0c;阴影都不需要特…

华为云云耀云服务器L实例评测-搭建基于hexo的个人博客

1、演示 访问地址&#xff1a;演示传送门开头先来一个效果图。 2、准备服务器 前面有介绍了一下华为云云耀云服务器L实例评测以及简单的配置用法&#xff0c;具体可以看上篇的博客。https://blog.csdn.net/yongqing_/article/details/132867889我这里用的是华为云云耀云服务器…

OpenAPI,连接新世界_三叠云

开放平台 路径 应用与导航 >> 开放平台 功能简介 随着企业数字化转型的不断深入&#xff0c;越来越多的公司需要与其他企业或应用程序进行集成&#xff0c;实现更高效和智能的业务流程。因此&#xff0c;三叠云提出了一种新的解决方案&#xff1a;开放平台。 三叠云…

OpenHarmony 系统能力 SystemCapability 使用指南

一、概述 1、系统能力与 API SysCap&#xff0c;全称 SystemCapability&#xff0c;即系统能力&#xff0c;指操作系统中每一个相对独立的特性&#xff0c;如蓝牙&#xff0c;WIFI&#xff0c;NFC&#xff0c;摄像头等&#xff0c;都是系统能力之一。每个系统能力对应多个 API&…