6

我刚读过

当我的 gcc C++ 应用程序崩溃时如何生成堆栈跟踪

现在已经很老了(5年)。一些答案建议的解决方案允许您为每个堆栈帧获取函数的名称和偏移量(我猜在堆栈内)。但我(可能还有其他人)真正需要的是进行调用的源文件名和行号(假设代码是使用调试信息编译的)。与执行此操作的 glibc 的一部分相关的答案之一(libSegfault;请参阅此目录中的文件- segfault.c, backtracesyms.c, backtracesymsfd.c) - 所以它是可能的

我的问题是:

  • 是否可以以独立于平台的方式或符合某些标准(POSIX??)的方式提取此信息
  • 为什么 libunwind 不支持这个?(我认为不是,在浏览了他们的网站后)
  • 这是否一定取决于您的编译器的 C/C++ 标准库(至少对于 C/C++ 应用程序)?

笔记:

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

2 回答 2

3

添加到@EmployedRussian 的有效答案 - 现在有一个多平台库可以执行此操作:

提升堆栈跟踪

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

// 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
于 2018-02-22T10:27:29.273 回答
2

是否可以以独立于平台的方式或符合某些标准(POSIX??)的方式提取此信息

除非有人编写了一个独立于平台的库来这样做。目前没有这样的库(我知道)。

此外,如果通过平台独立您的意思是“也适用于 Windows”,那么请注意,Windows 原生调试格式—— PDB, 直到最近才被专有和未记录。

为什么 libunwind 不支持这个?(我认为不是,在浏览了他们的网站后)

libunwind如果有人提供了这样的支持(你是自愿的吗?),可以支持这个。但是,这可能会使它的大小翻两番,而且它目前实际上没有得到维护。

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

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

PS 我认为对C标准库的依赖对你来说不是一个真正的问题。也可以独立于C库,但必须重新发明轮子而且没有实际理由这样做。

聚苯乙烯

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

是的,您需要复杂的代码,并且因平台而异。该代码是在 GDB 中还是在 GDB 中libunwind都不会改变这一点。

PPPS 还有lldb,它将大部分代码作为库提供(但我不确定该代码在各种平台上的成熟程度)。

于 2016-11-24T04:16:13.030 回答