我一直在使用backtrace和backtrace_symbols来生成编程堆栈跟踪,以便进行日志记录/诊断。它似乎粗略地工作,但是,我得到一点点修改,并且没有与每个函数调用相关联的文件/行号(正如我在gdb bt调用中所期望的那样)。这是一个例子:
1 leonardo 0x00006989 _ZN9ExceptionC2E13ExceptionType + 111
2 leonardo 0x00006a20 _ZN9ExceptionC1E13ExceptionType + 24
3 leonardo 0x0000ab64 _ZN5Rules11ApplyActionER16ApplicableActionR9GameState + 1060
4 leonardo 0x0000ed15 _ZN9Simulator8SimulateEv + 2179
5 leonardo 0x0000eec9 _ZN9Simulator8SimulateEi + 37
6 leonardo 0x00009729 main + 45
7 leonardo 0x000025c6 start + 54
我缺少什么东西,做些傻话,或者这是我在OS / X上的回溯所能期待的吗?
其他一些花絮:
rdynamic
链接选项。-g/-g3
没有任何区别。
abi::__cxa__demangle
似乎没有做任何事情
答案 0 :(得分:4)
回溯通常以以下格式从backtrace_symbols返回:
./ MyApp(_ZN4test3fooEv + 0x8)[0x821c874]
abi :: __ cxa_demangle只需要函数名称。因此,必须首先对跟踪进行一些解析:
std::string trace(backtrace[idx]);
// attempt to demangle
{
std::string::size_type begin, end;
// find the beginning and the end of the useful part of the trace
begin = trace.find_first_of('(') + 1;
end = trace.find_last_of('+');
// if they were found, we'll go ahead and demangle
if (begin != std::string::npos && end != std::string::npos) {
trace = trace.substr(begin, end - begin);
size_t maxName = 1024;
int demangleStatus;
char* demangledName = (char*) malloc(maxName);
if ((demangledName = abi::__cxa_demangle(trace.c_str(), demangledName, &maxName,
&demangleStatus)) && demangleStatus == 0) {
trace = demangledName; // the demangled name is now in our trace string
}
free(demangledName);
}
}
我已经在我自己的项目中进行了测试,它使用以下格式提供了更好的回溯:
测试:: foo的()
当然,没有行号,但我不确定是否可行。
答案 1 :(得分:2)
我不知道backtrace_symbols()
的任何实现,它提供的不仅仅是符号+偏移量。
关于abi:: __cxa__demangle
,您需要确保只传递符号名称,而不带+ line
后缀,否则它将无法将该符号识别为有效。