问题
I've just read
How to generate a stacktrace when my gcc C++ app crashes
which is pretty old by now (5 years). Some answers suggest solutions allowing you to get, for every stack frame, the name of the function and an offset (within the stack I guess). But what I (and may others) really need is the source filename and line number where the call was made (assuming the code was compiled with debug information). One of the answers linked to a part of glibc which does this (libSegfault; see files in this directory - segfault.c
, backtracesyms.c
, backtracesymsfd.c
) - so it is possible.
My questions are:
- Can this information be extracted in a platform-independent fashion, or one that conforms to some standard (POSIX??)
- Why doesn't libunwind support this? (I think it doesn't, after looking through ther website)
- Does this necessarily depend on your compiler's C/C++ standard library (for C/C++ apps, at least)?
Notes:
- You may assume the binary has debugging info, so in the case of C/C++ it was compiled with
-g
; of course, in a proper library we would check whether debug info is available or not.
回答1:
Can this information be extracted in a platform-independent fashion, or one that conforms to some standard (POSIX??)
Not unless someone writes a platform-independent library to do so. There are no such libraries (that I am aware of) at the moment.
Also, if by platform independent you mean "also works on Windows", then note that the Windows-native debugging format -- the PDB
, was proprietary and undocumented until very recently.
Why doesn't libunwind support this? (I think it doesn't, after looking through ther website)
libunwind
could support this if someone contributed such support (are you volunteering?). However, that would probably quadruple its size, and it currently is effectively unmaintained.
Does this necessarily depend on your compiler's C/C++ standard library (for C/C++ apps, at least)?
No, it only depends on the debug format. So long as the format is documented (e.g. DWARF4
on Linux and PDB
on Windows), it's possible to write a library to parse such format, and there is no reason for such library to necessarily depend on C++
standard library.
P.S. I assume that dependence on the C
standard library isn't a real concern for you. It's also possible to be independent of the C
library, but one would have to reinvent the wheel a lot, and there is no practical reason to do so.
P.P.S.
GDB has complex code that varies by platform to do it.
Yes, and you need that complex code, and it will vary by platform. Whether that code lives in GDB or in libunwind
doesn't change that.
P.P.P.S. There is also lldb
, which provides much of that code as a library (but I am not sure how mature that code on various platforms is).
回答2:
Adding to @EmployedRussian's valid answer - there is now a multi-platform library which does this:
Boost StackTrace
And just to illustrate what a trace looks like, if you were to write:
// 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();
you might get something like (on Linux for example):
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
来源:https://stackoverflow.com/questions/40751832/is-there-a-portable-standard-compliant-way-to-get-filenames-and-linenumbers-in-a