如何打印调用堆栈中的C / C ++更漂亮? [英] How to print call stack in C/C++ more beautifully?

查看:835
本文介绍了如何打印调用堆栈中的C / C ++更漂亮?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想打印调用栈与更像gdb的信息。

I would like to print call stack with more information like in 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]);
    }
}

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

When it runs, I get something as below.

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]

这是很难看的。有功能名称,它会好得多。
非常感谢您的提示。

It is hard to read. With function names, it would be much better. Thanks a lot for the tip.

推荐答案

免责声明:以下是主要用于使用GCC或锵用的libstdc ++ Linux,你可能需要在其他系统不同的方式

Disclaimer: The following is mostly for Linux using GCC or Clang with libstdc++, you might need different ways on other systems.

最重要的事情是 -rdynamic 连接时添加到命令行。如果这是必需的所有系统上的我不知道,但对我来说,这其实原来所有这些地址到符号。

The most important thing is to add -rdynamic to the command line when linking. I don't know if this is required on all systems, but for me, this actually turned all those addresses into symbols.

现在,你得到一些信息,你可能想还原函数的符号。开始时你有一个独立的功能来还原函数任何符号:

Now that you get some information, you probably want to demangle the symbols. You start with a stand-alone function to demangle any symbol:

// you most likely need these headers (plus stuff for std::cout, ...)
#include <cxxabi.h>
#include <execinfo.h>

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 终止,但以下工作得很好对我来说:

And now for the real thing. I don't know if the format of the output from backtrace_symbols is specified, but the following works quite well for me:

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 来适应我的$ C $,所以可能会有一些小怪癖那里 - 检查code。如果你的作品,如果没有,你需要帮助修复它,让我知道)。

(I had to adapt my code slightly since I'm not using std::cout, so there might be some little quirks there - check the code if it works for you and if not and you need help fixing it, let me know).

这篇关于如何打印调用堆栈中的C / C ++更漂亮?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆