三、进进介版代码,在第一,第二点的代码基础上改动
// The prefix used for mangled symbols, per the Itanium C++ ABI:
// http://www.codesourcery.com/cxx-abi/abi.html#mangling
const char kMangledSymbolPrefix[] = "_Z";
// Characters that can be used for symbols, generated by Ruby:
// (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
const char kSymbolCharacters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
// Demangles C++ symbols in the given text. Example:
// "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
// =>
// "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
void DemangleSymbol (std::string* symbol)
{
std::string::size_type search_from = 0;
while (search_from < symbol->size ()) {
// Look for the start of a mangled symbol from search_from
std::string::size_type mangled_start = symbol->find (kMangledSymbolPrefix, search_from);
if (mangled_start == std::string::npos) {
break; // Mangled symbol not found
}
// Look for the end of the mangled symbol
std::string::size_type mangled_end = symbol->find_first_not_of (kSymbolCharacters, mangled_start);
if (mangled_end == std::string::npos) {
mangled_end = symbol->size ();
}
std::string mangled_symbol = std::move (symbol->substr (mangled_start, mangled_end - mangled_start));
// Try to demangle the mangled symbol candidate
int status = -4; // some arbitrary value to eliminate the compiler warning
std::unique_ptr<char, void(*)(void*)> demangled_symbol {
abi::__cxa_demangle (mangled_symbol.c_str (), nullptr, 0, &status),
std::free
};
// 0 Demangling is success
if (0 == status) {
// Remove the mangled symbol
symbol->erase (mangled_start, mangled_end - mangled_start);
// Insert the demangled symbol
symbol->insert (mangled_start, demangled_symbol.get ());
// Next time, we will start right after the demangled symbol
search_from = mangled_start + strlen (demangled_symbol.get ());
}
else {
// Failed to demangle. Retry after the "_Z" we just found
search_from = mangled_start + 2;
}
}
}
该版本的DemangleSymbol函数与第二版的DemangleSymbol函数稍有改动,该版本主要是找到_Z13GetStackTracePSs这样的字符串给__cxa_demangle函数解析,最后将解析后的内容替换掉原来的内容,编译成可执行文件StackTrace后执行输出结果入下:
./StackTrace(GetStackTrace(std::string*)+0x27) [0x403720]
./StackTrace(TestFunc(std::string&, int)+0x2a) [0x4038c0]
./StackTrace(main+0x2d) [0x4038ef]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7fb9d560bde5]
./StackTrace() [0x403279]
以上输出结果在代码调试中能给我们带来很多的信息,但是还是少了一些辅助信息,例如:文件名、函数所在文件的代码行、进程或者线程号(这个在多线中很重要)。更多内容可以参考开源项目libunwind或者google-coredumper。








