首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在addr2line中直接使用c++

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

Stack Overflow用户
提问于 2018-08-17 09:08:48
回答 1查看 2.5K关注 0票数 2

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

我使用以下可以得到回溯行号的方法:

代码语言:javascript
复制
addr2line -e /home/roroco/Dropbox/c/ro-c/cmake-build-debug/ex/test_backtrace_with_line_number  0x400d0b

但是如果我想要得到回溯所有的行号,我必须逐行调用addr2line cli,这很慢,有没有办法获得没有cli但使用纯c++的回溯行号呢?或其他可选库可以获得行号。

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

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

代码语言:javascript
复制
#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;
}
EN

回答 1

Stack Overflow用户

发布于 2018-08-17 12:53:57

更改addr2line源代码是如此困难,我放弃了这种方式,我收到@500 -内部服务器错误建议,addr2line cli可以接收多个加载项,所以我更改代码如下,只运行addr2line一次

代码语言:javascript
复制
#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;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51891987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档