博客
关于我
C++封装一个易用的打印backtrace信息的函数
阅读量:733 次
发布时间:2019-03-21

本文共 2567 字,大约阅读时间需要 8 分钟。

如何通过C++编写一个易于使用的打印堆栈信息函数

  • 堆栈信息追踪的重要性

    在调试程序过程中,当遇到错误时,能够快速获取当前函数调用堆栈信息至关重要。通常,这会在调用assert函数之前进行,以便定位问题所在。

  • 查看所需的核心函数

  • 2.1 backtrace函数

    backtrace函数的原型为:

    int backtrace(void **buffer, int size);

    使用说明:

    该函数会将当前程序的堆栈信息写入buffer数组。每个数组元素是返回地址,信息是倒序存储的(最近调用在前,遥远调用在后)。通过确保buffer大小和容量足够,可以获取完整的堆栈日志。返回值表示实际获取到的堆栈信息数量,数值不会超过size

    2.2 backtrace_symbols函数

    backtrace_symbols函数的原型为:

    char **backtrace_symbols(void *const *buffer, int size);

    使用说明:

    该函数接受backtrace返回的地址数组,将其转换为字符串数组。每个字符串包含函数名(如果确定可知)、十六进制偏移量和实际返回地址。返回值是一个指针,指向新的字符串数组。注意,这个数组的内存必须由调用者释放,但字符串内容不需要处理。

    2.3 __cxa_demangle函数

    __cxa_demangle函数的原型为:

    char* __cxa_demangle(const char *mangled_name, char *output_buffer, size_t *length, int *status);

    使用说明:

    这个C++内联函数反转编译器添加的符号信息,将其转换为原始函数名。主要作用是解析 και符号sequences。调用者应提供被编译后的符号字符串,并处理返回结果,注意释放动态分配的内存。

    1. 测试各函数的实际使用情况
    2. 3.1 调用backtrace获取日志

      举例:

      void fun(){      static int count = 0;      if (++count == 5){          Backtrace(50, 0);          return;      }      fun();  }  int main(int argc, char* argv[]){      fun();      return 0;  }

      运行后,期望输出包含5次fun调用的堆栈信息。

      3.2 转换为符号名称

      调用backtrace_symbols后,输出应类似于:

      ./all(_Z9BacktraceiiRKSs+0x58) [0x401c43]./all(_Z3funv+0x48)...

      需要提取括号内的名称并解析。

      3.3 使用__cxa_demangle获取原始函数名

      最终结果应类似于:

      Backtrace(int, int, std::string const&).fun()fun()fun()fun()fun()./all(main+0x9)...

      结果表明,其中Backtrace被调用5次,遵循预期调用次数。

      1. 完整代码示例
      2. #include 
        #include
        #include
        #include
        #include
        #include
        #include
        #include
        namespace detail { std::string demangle(const char* str) { size_t size = 0; int status = 0; std::string sstr; sstr.resize(256); if (1 == sscanf(str, "%*[^(]%*[^_]%255[^)+]", &sstr[0])) { char* tmp = abi::__cxa_demangle(&sstr[0], nullptr, &size, &status); if (tmp) { std::string result(tmp); free(tmp); return result; } } if (1 == sscanf(str, "%255s", &sstr[0])) return sstr; return str; } std::string Backtrace(int size = 64, int skip = 2, const std::string& prefix = "") { void* array[size]; size_t s = backtrace(array, size); char** str = backtrace_symbols(array, s); std::vector
        bt; std::stringstream ss; if (str) { for (size_t i = skip; i < s; ++i) { bt.push_back(demangle(str[i])); } free(str); } else { ss << "backtrace_symbols failed"; goto good; } for (const auto& b : bt) { ss << prefix << b << "\n"; }good: return ss.str(); } void fun() { static int count = 0; if (++count == 5) { Backtrace(50, 0); return; } fun(); } int main(int argc, char* argv[]) { fun(); return 0; }}

        以上代码展示了一个完整的解决方案,包括函数定义、调试工具的使用和示例测试程序。通过这种方法,可以方便地获取和解析堆栈信息,使调试过程更加高效。

    转载地址:http://wxsgz.baihongyu.com/

    你可能感兴趣的文章
    nginx配置详解、端口重定向和504
    查看>>
    Nginx配置负载均衡到后台网关集群
    查看>>
    Nginx配置限流,技能拉满!
    查看>>
    Nginx面试三连问:Nginx如何工作?负载均衡策略有哪些?如何限流?
    查看>>
    Nginx:NginxConfig可视化配置工具安装
    查看>>
    ngModelController
    查看>>
    ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
    查看>>
    NHibernate学习[1]
    查看>>
    NHibernate异常:No persister for的解决办法
    查看>>
    NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
    查看>>
    NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_更新时如果目标表中不存在记录就改为插入数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0059
    查看>>
    NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
    查看>>
    NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
    查看>>
    NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表或全表增量同步_实现指定整库同步_或指定数据表同步配置_04---大数据之Nifi工作笔记0056
    查看>>
    NIFI1.23.2_最新版_性能优化通用_技巧积累_使用NIFI表达式过滤表_随时更新---大数据之Nifi工作笔记0063
    查看>>
    NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_根据binlog实现数据实时delete同步_实际操作04---大数据之Nifi工作笔记0043
    查看>>
    NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置binlog_使用处理器抓取binlog数据_实际操作01---大数据之Nifi工作笔记0040
    查看>>
    NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
    查看>>
    NIFI从MySql中离线读取数据再导入到MySql中_03_来吧用NIFI实现_数据分页获取功能---大数据之Nifi工作笔记0038
    查看>>
    NIFI从MySql中离线读取数据再导入到MySql中_无分页功能_02_转换数据_分割数据_提取JSON数据_替换拼接SQL_添加分页---大数据之Nifi工作笔记0037
    查看>>