c++ - 如何在c++中直接使用addr2line

标签 c++ linux c++11

更新:this question无法解决我的需求,addr2line 源不仅是 400 行源,它与其他 binutils 源相关,我想要一个简单的解决方案来执行“获取回溯行号”

我使用以下可以获取回溯行号的方法:

addr2line -e /home/roroco/Dropbox/c/ro-c/cmake-build-debug/ex/test_backtrace_with_line_number  0x400d0b

但是如果我想获取回溯所有行号,我必须逐行调用 addr2line cli,它很慢,有没有办法在没有 cli 的情况下使用纯 c++ 获取回溯行号?或者其他替代库可以获得行号

我知道如果我看到addr2line,我可以这样做,如果有更方便的c++ lib,请告诉我

这是我使用 addr2line 获取行号的代码,我希望用纯 C++ 解决方案来代替 addr2line cli

#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <zconf.h>
#include "regex"

std::string getexepath() {
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
}

std::string sh(std::string cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
            result += buffer.data();
        }
    }
    return result;
}


void print_backtrace(void) {
    void *bt[1024];
    int bt_size;
    char **bt_syms;
    int i;

    bt_size = backtrace(bt, 1024);
    bt_syms = backtrace_symbols(bt, bt_size);
    std::regex re("\\[(.+)\\]");
    auto exec_path = getexepath();
    for (i = 1; i < bt_size; i++) {
        std::string sym = bt_syms[i];
        std::smatch ms;
        if (std::regex_search(sym, ms, re)) {
            std::string addr = ms[1];
            std::string cmd = "addr2line -e " + exec_path + " -f -C " + addr;
            auto r = sh(cmd);
            std::regex re2("\\n$");
            auto r2 = std::regex_replace(r, re2, "");
            std::cout << r2 << std::endl;
        }
    }
    free(bt_syms);
}

void test_m() {
    print_backtrace();
}

int main() {
    test_m();
    return 0;
}

最佳答案

改变 addr2line 源太难了,我放弃了, 我收到 @500 - Internal Server Error 建议,addr2line cli 可以接收多个地址,所以我像下面这样更改我的代码,只运行 addr2line 一次

#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <zconf.h>
#include "regex"
#include "vector"

std::string getexepath() {
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
}

std::string sh(std::string cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
            result += buffer.data();
        }
    }
    return result;
}


void print_backtrace(void) {
    void *bt[1024];
    int bt_size;
    char **bt_syms;
    int i;

    bt_size = backtrace(bt, 1024);
    bt_syms = backtrace_symbols(bt, bt_size);
    std::regex re("\\[(.+)\\]");
    auto exec_path = getexepath();
    std::string addrs = "";
    for (i = 1; i < bt_size; i++) {
        std::string sym = bt_syms[i];
        std::smatch ms;
        if (std::regex_search(sym, ms, re)) {
            std::string m = ms[1];
            addrs += " " + m;
        }
    }
    auto r = sh("addr2line -e " + exec_path + " -f -C " + addrs);
    std::cout << r << std::endl;
    free(bt_syms);
}

void test_m() {
    print_backtrace();
}

int main() {
    test_m();
    return 0;
}

关于c++ - 如何在c++中直接使用addr2line,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51891987/

相关文章:

c++ - 我正在尝试在 ubuntu 14 上安装 libgtk2.0-dev 但出现一些错误

c++ - 在 Mac 上找不到 Qt 库

c++ - STL set_intersection 运行时错误

c++ - 传递给 std::basic_string 的分配器能否具有其虚拟方法

c++ - 如何权衡精度和速度以评估 C++ 中两个 vector 的点积符号? (不是硬件特定的)

c++ - C++ 中的顺序遍历算法的执行策略是如何工作的?

Linux 静态驱动加载问题

linux - 根据第一个字符有条件地将字符添加到输入行

linux - rsync 包含文件递归

c++ - 在 lambda 表达式中捕获指针?