是否有一种可移植/符合标准的方法来获取堆栈跟踪中的文件名和行号?

问题描述 投票:0回答:3

我刚刚读过

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

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

segfault.c
backtracesyms.c
backtracesymsfd.c
) - 所以它是可能

我的问题是:

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

备注:

  • 您可能会假设二进制文件具有调试信息,因此在 C/C++ 的情况下,它是用
    -g
    编译的;当然,在适当的库中,我们会检查调试信息是否可用。
c++ c stack-trace glibc libunwind
3个回答
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

2
投票

能否以一种独立于平台的方式或符合某种标准(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

,它以库的形式提供了大部分代码(但我不确定这些代码在各个平台上的成熟程度)。

    


0
投票

正如 einpoklum 指出的那样,有 boost stacktrace,但该库依赖于外部依赖项并存在可移植性问题。另外请注意,如果没有

safe_dump_to

,它的堆栈跟踪生成不是异步信号安全的。

Cpptrace

是一个用于 C++11 及更高版本的简单且可移植的堆栈跟踪库。它当前不支持信号安全跟踪,但它提供了一个原始跟踪接口,可用于稍后解析程序计数器向量。结合第一篇文章中提到的问题,如何在程序崩溃时自动生成堆栈跟踪,可以使用 backtrace 生成堆栈跟踪,然后将其交给 cpptrace 来解析。

    

© www.soinside.com 2019 - 2024. All rights reserved.