我刚刚读过
现在已经很老了(5年)。一些答案提出了解决方案,允许您为每个堆栈帧获取函数的名称和偏移量(我猜是在堆栈内)。但我(以及可能其他人)真正需要的是进行调用的源文件名和行号(假设代码是使用调试信息编译的)。链接到执行此操作的 glibc 一部分的答案之一(libSegfault;请参阅此目录中的文件 -
segfault.c
,backtracesyms.c
,backtracesymsfd.c
) - 所以它是可能。
我的问题是:
备注:
-g
编译的;当然,在适当的库中,我们会检查调试信息是否可用。添加@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
能否以一种独立于平台的方式或符合某种标准(POSIX??)的方式提取此信息
除非有人编写一个独立于平台的库来这样做。目前没有这样的库(据我所知)。
此外,如果您所说的独立于平台是指“也适用于 Windows”,那么请注意,Windows 原生调试格式——
PDB
,直到最近都是专有的且没有文档记录。
为什么libunwind不支持这个? (浏览他们的网站后我认为不是)
libunwind
可以支持这个如果有人贡献了这样的支持(你是志愿者吗?)。然而,这可能会使它的大小增加四倍,而且它目前“有效地”未得到维护。
这是否一定取决于编译器的 C/C++ 标准库(至少对于 C/C++ 应用程序)?不,它仅取决于调试格式。只要记录了格式(例如 Linux 上的
DWARF4
和 Windows 上的
PDB
),就可以编写一个库来解析这种格式,并且这样的库没有必要依赖于 C++
标准库.附注我认为对
C
标准库的依赖并不是您真正关心的问题。也可以独立于
C
库,但必须重新发明轮子很多,而且没有实际理由这样做。 P.P.S.
GDB 具有复杂的代码,该代码因平台而异。
需要是的,您
复杂的代码,并且它会因平台而异。无论该代码位于 GDB 中还是位于 libunwind
中都不会改变这一点。
P.P.P.S。还有
lldb
,它以库的形式提供了大部分代码(但我不确定这些代码在各个平台上的成熟程度)。
正如 einpoklum 指出的那样,有 boost stacktrace,但该库依赖于外部依赖项并存在可移植性问题。另外请注意,如果没有
safe_dump_to
,它的堆栈跟踪生成不是异步信号安全的。
Cpptrace 是一个用于 C++11 及更高版本的简单且可移植的堆栈跟踪库。它当前不支持信号安全跟踪,但它提供了一个原始跟踪接口,可用于稍后解析程序计数器向量。结合第一篇文章中提到的问题,如何在程序崩溃时自动生成堆栈跟踪,可以使用 backtrace
生成堆栈跟踪,然后将其交给 cpptrace 来解析。