更新: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++库,请告诉我
下面是我用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;
}发布于 2018-08-17 12:53:57
更改addr2line源代码是如此困难,我放弃了这种方式,我收到@500 -内部服务器错误建议,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;
}https://stackoverflow.com/questions/51891987
复制相似问题