是否有 portable/standard-compliant 方法在堆栈跟踪中获取文件名和行号?
Is there a portable/standard-compliant way to get filenames and linenumbers in a stack trace?
我刚读完
How to generate a stacktrace when my gcc C++ app crashes
现在已经很老了(5 年)。一些答案建议的解决方案允许您为每个堆栈帧获取函数名称和偏移量(我猜是在堆栈内)。但我(可能还有其他人)真正需要的是进行调用的源文件名和行号(假设代码是使用调试信息编译的)。与执行此操作的 glibc 的一部分相关联的答案之一(libSegfault;请参阅 this directory 中的文件 - segfault.c
、backtracesyms.c
、backtracesymsfd.c
)- 所以它是 可能.
我的问题是:
- 能否以独立于平台的方式或符合某些标准的方式提取此信息 (POSIX??)
- 为什么 libunwind 不支持这个? (我认为不是,看了之后website)
- 这是否一定取决于编译器的 C/C++ 标准库(至少对于 C/C++ 应用程序)?
备注:
- 你可能假设二进制文件有调试信息,所以在 C/C++ 的情况下,它是用
-g
编译的;当然,在适当的库中,我们会检查调试信息是否可用。
Can this information be extracted in a platform-independent fashion, or one that conforms to some standard (POSIX??)
除非有人为此编写了一个独立于平台的库,否则不会。目前没有这样的库(据我所知)。
此外,如果您所说的独立于平台的意思是 "also works on Windows",请注意 Windows- 本地调试格式 -- PDB
直到最近都是专有的并且没有记录。
Why doesn't libunwind support this? (I think it doesn't, after looking through ther website)
libunwind
可以支持此 如果 有人贡献了这种支持(你是自愿的吗?)。但是,这可能会使它的大小增加四倍,并且它目前 有效地 未维护。
Does this necessarily depend on your compiler's C/C++ standard library (for C/C++ apps, at least)?
不,这只取决于调试格式。只要记录了格式(例如 Linux 上的 DWARF4
和 Windows 上的 PDB
,就可以编写一个库来解析这种格式,没有理由这样的库必然依赖于 C++
标准库。
P.S。我认为对 C
标准库的依赖并不是您真正关心的问题。也可以独立于 C
库,但必须重新发明轮子 很多 ,并且没有实际理由这样做。
P.P.S.
GDB has complex code that varies by platform to do it.
是的,您需要复杂的代码,它将因平台而异。无论该代码存在于 GDB 中还是存在于 libunwind
中都不会改变这一点。
P.P.P.S。还有 lldb
,它提供了大部分代码作为库(但我不确定各种平台上的代码有多成熟)。
添加到@EmployedRussian 的有效答案 - 现在有一个 multi-platform 库可以执行此操作:
为了说明跟踪的样子,如果您要写:
// This following definition may be necessary to ensure you can get
// line numbers included in the stack trace; see:
//
// 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
我刚读完
How to generate a stacktrace when my gcc C++ app crashes
现在已经很老了(5 年)。一些答案建议的解决方案允许您为每个堆栈帧获取函数名称和偏移量(我猜是在堆栈内)。但我(可能还有其他人)真正需要的是进行调用的源文件名和行号(假设代码是使用调试信息编译的)。与执行此操作的 glibc 的一部分相关联的答案之一(libSegfault;请参阅 this directory 中的文件 - segfault.c
、backtracesyms.c
、backtracesymsfd.c
)- 所以它是 可能.
我的问题是:
- 能否以独立于平台的方式或符合某些标准的方式提取此信息 (POSIX??)
- 为什么 libunwind 不支持这个? (我认为不是,看了之后website)
- 这是否一定取决于编译器的 C/C++ 标准库(至少对于 C/C++ 应用程序)?
备注:
- 你可能假设二进制文件有调试信息,所以在 C/C++ 的情况下,它是用
-g
编译的;当然,在适当的库中,我们会检查调试信息是否可用。
Can this information be extracted in a platform-independent fashion, or one that conforms to some standard (POSIX??)
除非有人为此编写了一个独立于平台的库,否则不会。目前没有这样的库(据我所知)。
此外,如果您所说的独立于平台的意思是 "also works on Windows",请注意 Windows- 本地调试格式 -- PDB
直到最近都是专有的并且没有记录。
Why doesn't libunwind support this? (I think it doesn't, after looking through ther website)
libunwind
可以支持此 如果 有人贡献了这种支持(你是自愿的吗?)。但是,这可能会使它的大小增加四倍,并且它目前 有效地 未维护。
Does this necessarily depend on your compiler's C/C++ standard library (for C/C++ apps, at least)?
不,这只取决于调试格式。只要记录了格式(例如 Linux 上的 DWARF4
和 Windows 上的 PDB
,就可以编写一个库来解析这种格式,没有理由这样的库必然依赖于 C++
标准库。
P.S。我认为对 C
标准库的依赖并不是您真正关心的问题。也可以独立于 C
库,但必须重新发明轮子 很多 ,并且没有实际理由这样做。
P.P.S.
GDB has complex code that varies by platform to do it.
是的,您需要复杂的代码,它将因平台而异。无论该代码存在于 GDB 中还是存在于 libunwind
中都不会改变这一点。
P.P.P.S。还有 lldb
,它提供了大部分代码作为库(但我不确定各种平台上的代码有多成熟)。
添加到@EmployedRussian 的有效答案 - 现在有一个 multi-platform 库可以执行此操作:
为了说明跟踪的样子,如果您要写:
// This following definition may be necessary to ensure you can get
// line numbers included in the stack trace; see:
//
// 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