是否有可移植/符合标准的方法来获取堆栈跟踪中的文件名和亚麻布?

时间:2016-11-22 21:19:48

标签: c++ c stack-trace glibc libunwind

我刚看完

How to generate a stacktrace when my gcc C++ app crashes

现在已经很久了(5年)。一些答案提出了解决方案,允许您为每个堆栈帧获取函数的名称和偏移量(我猜在堆栈内)。但是我(以及其他人)真正需要的是调用源的文件名和行号(假设代码是使用调试信息编译的)。其中一个答案与glibc的一部分相关联(libSegfault;参见this directory中的文件 - segfault.cbacktracesyms.cbacktracesymsfd.c) - 所以它是可能

我的问题是:

  • 这些信息可以以独立于平台的方式提取,还是符合某种标准(POSIX ??)
  • 为什么libunwind不支持这个? (通过website
  • 查看认为没有
  • 这是否一定取决于编译器的C / C ++标准库(至少对于C / C ++应用程序)?

备注:

  • 您可以假设二进制文件具有调试信息,因此在C / C ++的情况下,它使用-g编译;当然,在适当的库中,我们会检查调试信息是否可用。

2 个答案:

答案 0 :(得分:3)

添加@ EmployedRussian的有效答案 - 现在有一个多平台库可以做到这一点:

Boost StackTrace

只是为了说明跟踪的样子,如果你要写:

// This following definition may be necessary to ensure you can get
// line numbers included in the stack trace; see:
// https://stackoverflow.com/questions/3899870/
// for details
//
#define BOOST_STACKTRACE_USE_ADDR2LINE

#include <boost/stacktrace.hpp>

// ... somewhere inside the `bar(int)` function that is called recursively:
std::cout << boost::stacktrace::stacktrace();

你可能会得到类似的东西(例如在Linux上):

0# bar(int) at /path/to/source/file.cpp:70
1# bar(int) at /path/to/source/file.cpp:70
2# bar(int) at /path/to/source/file.cpp:70
3# bar(int) at /path/to/source/file.cpp:70
4# main at /path/to/main.cpp:93
5# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
6# _start

答案 1 :(得分:2)

  

这些信息可以以独立于平台的方式提取,还是符合某种标准(POSIX ??)

除非有人编写与平台无关的库,否则不会这样做。目前没有这样的库(我知道)。

另外,如果你的平台独立意味着&#34;也适用于Windows&#34;,那么请注意,Windows本机调试格式 - PDB是专有的,直到最近才被记录。< / p>

  

为什么libunwind不支持这个? (我认为通过网站查看后它并没有)

libunwind可以支持,如果有人提供此类支持(您是否自愿参与?)。但是,这可能会使其规模翻两番,目前实际上未维护。

  

这是否一定取决于您的编译器的C / C ++标准库(至少对于C / C ++应用程序)?

不,它只取决于调试格式。只要格式化(例如Linux上的DWARF4和Windows上的PDB),就可以编写一个库来解析这种格式,并且没有理由将这样的库用于必须依赖于C++标准库。

P.S。我认为对C标准库的依赖并不是你真正关心的问题。它也可以独立于C库,但是必须重新发明轮子 lot ,并且没有实际的理由这样做。

P.P.S。

  

GDB的代码复杂,因平台而异。

是的,您需要这个复杂的代码,而因平台而异。该代码是否存在于GDB或libunwind中并不会改变它。

P.P.P.S。还有lldb,它提供了大部分代码作为库(但我不确定各种平台上的代码有多成熟)。