如何更好地打印C / C ++中的调用堆栈?

我想打印调用堆栈与更多信息,如在gdb中。

这就是我到目前为止所拥有的。

void to_print_callstack() { void *buffer[100]; int n = backtrace(buffer,10); char **str = backtrace_symbols(buffer, n); for (int i = 0; i < n; i++) { printf("%d: %s\n", i, str[i]); } } 

当它运行时,我得到如下的东西。

 0: ./test-prog() [0x4466bf] 1: ./test-prog() [0x445e1d] 2: ./test-prog() [0x443fd5] 3: ./test-prog() [0x439a99] 4: ./test-prog() [0x43302f] 5: ./test-prog() [0x4322c9] 6: ./test-prog() [0x4320cd] 7: ./test-prog() [0x43e76b] 8: /lib/libc.so.6(__libc_start_main+0xfd) [0x7fc4de7d8c4d] 9: ./test-prog() [0x431569] 

很难读懂。 使用函数名称会更好。 非常感谢小费。

免责声明:以下主要是针对使用GCC的Linux或使用libstdc ++的Clang,您可能需要在其他系统上使用不同的方法。

最重要的是在-rdynamic时将-rdynamic添加到命令行。 我不知道这是否是所有系统都需要的,但对我来说,这实际上将所有这些地址都变成了符号。

现在您获得了一些信息,您可能想要对符号进行解码。 您从一个独立的函数开始解码任何符号:

 // you most likely need these headers (plus stuff for std::cout, ...) #include  #include  std::string demangle( const char* const symbol ) { const std::unique_ptr< char, decltype( &std::free ) > demangled( abi::__cxa_demangle( symbol, 0, 0, 0 ), &std::free ); if( demangled ) { return demangled.get(); } else { return symbol; } } 

而现在是真实的。 我不知道是否指定了backtrace_symbols的输出格式,但以下对我来说效果很好:

 void backtrace() { // TODO: replace hardcoded limit? void* addresses[ 256 ]; const int n = ::backtrace( addresses, std::extent< decltype( addresses ) >::value ); const std::unique_ptr< char*, decltype( &std::free ) > symbols( ::backtrace_symbols( addresses, n ), &std::free ); for( int i = 0; i < n; ++i ) { // we parse the symbols retrieved from backtrace_symbols() to // extract the "real" symbols that represent the mangled names. char* const symbol = symbols.get()[ i ]; char* end = symbol; while( *end ) { ++end; } // scanning is done backwards, since the module name // might contain both '+' or '(' characters. while( end != symbol && *end != '+' ) { --end; } char* begin = end; while( begin != symbol && *begin != '(' ) { --begin; } if( begin != symbol ) { std::cout << std::string( symbol, ++begin - symbol ); *end++ = '\0'; std::cout << demangle( begin ) << '+' << end; } else { std::cout << symbol; } std::cout << std::endl; } } 

(我不得不稍微调整我的代码,因为我没有使用std::cout ,所以可能会有一些小问题 - 检查代码是否适用于你,如果没有,你需要帮助修复它,让我知道) 。