我遇到了一个问题,而要跟踪一些信息的程序捕获异常.
我使用了下面的函数:
extern "C" void log_backtrace()
{
// Dump the callstack
int callstack[128];
int frames = backtrace((void**) callstack, 128);
char** strs = backtrace_symbols((void**) callstack, frames);
for (int i = 1; i < frames; ++i)
{
char functionSymbol[64*1024];
char moduleName [64*1024];
int offset = 0;
sscanf(strs[i], "%*d %s %*s %s %*s %d", &moduleName, &functionSymbol, &offset);
int addr = callstack[i];
int validCppName;
char* functionName = abi::__cxa_demangle(functionSymbol, NULL, 0,
&validCppName);
if (validCppName == 0)
printf( "\t%8.8x — %s + %d\t\t(%s)\n", addr, functionName, offset, moduleName);
else
printf( "\t%8.8x — %s + %d\t\t(%s)\n", addr, functionSymbol, offset, moduleName);
if (functionName)
free(functionName);
}
free(strs);
}
输出如下所示:
20:48:44 [ERROR]tcp_client::connect() failed. error:Connection refused
00000001 — latte::Log::out_error(std::string const&) + 151 (valhalla)
001a6637 — latte::tcp_client::connect(boost::asio::ip::basic_endpoint<boost::asio::ip::tcp> const&) + 307 (valhalla)
00000001 — valhalla::hall::start() + 388 (valhalla)
00204803 — main + 388 (valhalla)
00000001 — start + 52 (valhalla)
00143ae4 — 0x0 + 1 (???)
所有的信息(名称空间,类名和方法名)都很好。但唯一的问题是行号是错误的。
我怎样才能修正回溯中的行号?
3条答案
按热度按时间amrnrhlw1#
它们不是行号,而是从函数开始的偏移量。有一个叫做
addr2line
的工具,它是随binutils一起提供的,可以在给定调试符号的情况下将地址转换成行号。你可以在你的程序中调用它(pipe()
+fork()
+exec()
),或者查看它用来做这件事的库。在我的Linux系统上,addr2line在内部使用libbfd来完成这个任务,虽然从我所看到的来看,它没有得到很好的记录,但是通过addr2line源代码中的示例可以很容易地看到它。
5cg8jx4n2#
我也遇到了同样的问题,四处寻找解决方案,但是我什么也没找到。你在帖子中标记了OSX,所以我假设这是你想要的平台?OSX没有addr 2line,至少在OSX版本10.8/10.9中没有。我把代码放在下面(使用来自不同来源的代码片段),它生成的回溯看起来像这样(它包含了异常处理程序的前两个帧,如果你愿意,可以跳过这一步):
它只为执行模块中的帧生成函数+文件+行号。代码只在OSX上工作,但可以调整为在其他平台上工作。将有一些角落的情况没有涵盖,但希望这是一个很好的起点。代码是:
pqwbnv8z3#
我意识到最初的问题已经有十多年的历史了--但我也有同样的问题,而且刚刚找到了答案。我在Mac上使用cmake为AppleClang生成makefile。
如果你使用cmake来编译你的可执行文件--你需要传入“-g”编译器选项--就像这样:
添加编译选项(-g)
然后需要使用lldb运行可执行文件,如下所示:
远程数据库
然后在lldb命令行中-你需要使用命令“run”,然后你需要发出回溯命令“bt”,然后你最终会得到你崩溃的行号。