当我的程序崩溃时如何自动生成堆栈跟踪
我正在使用 GCC 编译器在 Linux 上工作。 当我的 C++ 程序崩溃时,我希望它自动生成堆栈跟踪。
我的程序由许多不同的用户运行,它也可以在 Linux、Windows 和 Macintosh 上运行(所有版本都是使用 gcc
编译的)。
我希望我的程序能够在崩溃时生成堆栈跟踪,并且用户下次运行它时,它会询问他们是否可以将堆栈跟踪发送给我,以便我可以追踪问题。 我可以处理向我发送信息,但我不知道如何生成跟踪字符串。 有任何想法吗?
I am working on Linux with the GCC compiler. When my C++ program crashes I would like it to automatically generate a stacktrace.
My program is being run by many different users and it also runs on Linux, Windows and Macintosh (all versions are compiled using gcc
).
I would like my program to be able to generate a stack trace when it crashes and the next time the user runs it, it will ask them if it is ok to send the stack trace to me so I can track down the problem. I can handle the sending the info to me but I don't know how to generate the trace string. Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
可能值得一看 Google Breakpad,它是一个跨平台故障转储生成器和处理转储的工具。
Might be worth looking at Google Breakpad, a cross-platform crash dump generator and tools to process the dumps.
某些版本的 libc 包含处理堆栈跟踪的函数; 您也许可以使用它们:
http://www.gnu.org /software/libc/manual/html_node/Backtraces.html
我记得使用 libunwind 很长一段时间不久前获取堆栈跟踪,但您的平台可能不支持它。
Some versions of libc contain functions that deal with stack traces; you might be able to use them:
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
I remember using libunwind a long time ago to get stack traces, but it may not be supported on your platform.
我忘记了 GNOME 的“apport”技术,但我不太了解如何使用它。 它用于生成堆栈跟踪和其他处理诊断信息,并可以自动提交错误。 这当然值得检查。
I forgot about the GNOME tech of "apport", but I don't know much about using it. It is used to generate stacktraces and other diagnostics for processing and can automatically file bugs. It's certainly worth checking in to.
是一个系统变量,它将允许在应用程序崩溃后创建核心转储。 在这种情况下,数量不受限制。 在同一目录中查找名为 core 的文件。 确保您在启用调试信息的情况下编译了代码!
问候
is a system variable, wich will allow to create a core dump after your application crashes. In this case an unlimited amount. Look for a file called core in the very same directory. Make sure you compiled your code with debugging informations enabled!
regards
作为仅限 Windows 的解决方案,您可以使用 Windows 错误报告。 只需几个注册表项,就可以将其设置为收集用户-模式转储:
您可以从具有所需权限的安装程序设置注册表项。
与在客户端上生成堆栈跟踪相比,创建用户模式转储具有以下优点:
请注意,WER 只能由应用程序崩溃触发(即系统由于未处理的异常而终止进程)。
MiniDumpWriteDump
可以随时调用。 如果您需要转储当前状态来诊断崩溃以外的问题,这可能会很有帮助。如果您想评估小型转储的适用性,则必须阅读:
As a Windows-only solution, you can get the equivalent of a stack trace (with much, much more information) using Windows Error Reporting. With just a few registry entries, it can be set up to collect user-mode dumps:
You can set the registry entries from your installer, which has the required privileges.
Creating a user-mode dump has the following advantages over generating a stack trace on the client:
Take note, that WER can only be triggered by an application crash (i.e. the system terminating a process due to an unhandled exception).
MiniDumpWriteDump
can be called at any time. This may be helpful if you need to dump the current state to diagnose issues other than a crash.Mandatory reading, if you want to evaluate the applicability of mini dumps:
我将使用在 Visual Leak Detector。 不过,这只适用于 Win32。
I would use the code that generates a stack trace for leaked memory in Visual Leak Detector. This only works on Win32, though.
我在这里看到了很多执行信号处理程序然后退出的答案。
这是正确的方法,但请记住一个非常重要的事实:如果您想获取生成的错误的核心转储,则不能调用
exit(status)
。 而是调用abort()
!I have seen a lot of answers here performing a signal handler and then exiting.
That's the way to go, but remember a very important fact: If you want to get the core dump for the generated error, you can't call
exit(status)
. Callabort()
instead!我发现@tgamblin 解决方案并不完整。
它无法处理 stackoverflow。
我认为因为默认情况下信号处理程序是使用相同的堆栈调用的
SIGSEGV 被抛出两次。 为了保护您需要为信号处理程序注册一个独立的堆栈。
您可以使用下面的代码来检查这一点。 默认情况下,处理程序失败。 使用定义的宏 STACK_OVERFLOW 就可以了。
I found that @tgamblin solution is not complete.
It cannot handle with stackoverflow.
I think because by default signal handler is called with the same stack and
SIGSEGV is thrown twice. To protect you need register an independent stack for the signal handler.
You can check this with code below. By default the handler fails. With defined macro STACK_OVERFLOW it's all right.
请参阅 ACE(自适应通信环境)中的堆栈跟踪工具。 它已经涵盖所有主要平台(以及更多)。 该库采用 BSD 风格许可,因此如果您不想使用 ACE,您甚至可以复制/粘贴代码。
See the Stack Trace facility in ACE (ADAPTIVE Communication Environment). It's already written to cover all major platforms (and more). The library is BSD-style licensed so you can even copy/paste the code if you don't want to use ACE.
我可以帮助Linux版本:可以使用函数backtrace、backtrace_symbols和backtrace_symbols_fd。 请参阅相应的手册页。
I can help with the Linux version: the function backtrace, backtrace_symbols and backtrace_symbols_fd can be used. See the corresponding manual pages.
*尼克:
您可以拦截 SIGSEGV (通常在崩溃之前引发此信号)并将信息保存到文件中。 (例如,除了可以使用 gdb 进行调试的核心文件之外)。
赢:
从 msdn 检查此。
你还可以查看google的chrome代码,看看它是如何处理崩溃的。 它有一个很好的异常处理机制。
*nix:
you can intercept SIGSEGV (usualy this signal is raised before crashing) and keep the info into a file. (besides the core file which you can use to debug using gdb for example).
win:
Check this from msdn.
You can also look at the google's chrome code to see how it handles crashes. It has a nice exception handling mechanism.
查看:
man 3 backtrace
并且:
这些是 GNU 扩展。
Look at:
man 3 backtrace
And:
These are GNU extensions.
如果您仍然想像我一样单独进行,您可以链接到
bfd
并避免使用addr2line
,就像我在这里所做的那样:https://github.com/gnif/LookingGlass/blob/master/common/src/ platform/linux/crash.c
这会产生输出:
If you still want to go it alone as I did you can link against
bfd
and avoid usingaddr2line
as I have done here:https://github.com/gnif/LookingGlass/blob/master/common/src/platform/linux/crash.c
This produces the output:
除了上述答案之外,这里还介绍了如何使 Debian Linux 操作系统生成核心转储
在底部输入以下内容:“kernel.core_pattern = /home//coredumps/%e_%t.dump”。 (%e将是进程名称,%t将是系统时间)
检查 /proc/sys/kernel/core_pattern 并验证它是否与您刚刚输入的内容匹配。
In addition to above answers, here how you make Debian Linux OS generate core dump
Enter the following at the bottom: “kernel.core_pattern = /home//coredumps/%e_%t.dump”. (%e will be the process name, and %t will be the system time)
Check /proc/sys/kernel/core_pattern and verify that this matches what you just typed in.
在 Linux/unix/MacOSX 上使用核心文件(您可以使用 ulimit 或 兼容的方式启用它们系统调用)。 在 Windows 上使用 Microsoft 错误报告(您可以成为合作伙伴并访问您的应用程序崩溃数据)。
On Linux/unix/MacOSX use core files (you can enable them with ulimit or compatible system call). On Windows use Microsoft error reporting (you can become a partner and get access to your application crash data).
迄今为止我最好的异步信号安全尝试
如果它实际上并不安全,请告诉我。 我还找不到显示行号的方法。
stacktrace_on_signal_safe.cpp
编译并运行:
需要
-rdynamic
来获取函数名称:然后我们可以将其通过管道传输到
c++filt
来分解:给出:
缺少几个级别由于优化,使用
-O0
我们得到更完整的结果:行号不存在,但我们可以使用
addr2line
获取它们。 这需要在不使用-rdynamic
的情况下进行构建:生成:
awk
解析非-rdynamic
+如果您还想将实际信号编号打印到标准输出,这里有一个异步信号安全实现 int 到字符串: 使用写入或异步安全函数从信号处理程序中打印 int,因为
printf
不是。在 Ubuntu 22.04 上测试。
C++23
与许多其他答案一样,本节忽略了问题的异步信号安全方面,这可能导致您的代码在崩溃时陷入死锁,这可能严肃点。 我们只能希望有一天 C++ 标准会添加一个类似 boost::stacktrace::safe_dump_to 的函数来一劳永逸地解决这个问题。
这将是通常更优越的 C++ 堆栈跟踪选项,如以下所述:如何在调用某个函数时打印堆栈跟踪,因为它显示行号并自动为我们进行整理。
stacktrace_on_signal.cpp
编译并运行:
从源代码编译的 GCC 12.1 上的输出,Ubuntu 22.04:
我认为由于打开了优化,它错过了
my_func_1
,据我所知,我们通常对此无能为力。 使用-O0
会更好:但不确定为什么
main
没有出现在那里。backtrace_simple
https://github.com/gcc-mirror/gcc/blob/releases/gcc-12.1.0/libstdc%2B %2B-v3/src/libbacktrace/backtrace-supported.h.in#L45 提到
backtrace_simple
是安全的:但它看起来使用起来不太方便,主要是一个内部工具。
std::basic_stacktrace
这是
std::stacktrace
的基础:https://en.cppreference.com/w/cpp/utility/basic_stacktrace它有一个分配器参数,cppreference 描述为:
所以我想知道
basic_stacktrace
本身是否是异步信号安全的,并且是否不可能制作一个也带有自定义分配器的std::stacktrace
版本,例如:boost::stacktrace::safe_dump_to
https://apolukhin.github.io/papers/stacktrace_r1.html 可能是收到的提案,提到:
只是获取核心转储?
核心转储允许您使用 GDB 检查内存:当程序具有命令行参数时,如何使用 GDB 分析程序的核心转储文件? 所以它比仅仅拥有痕迹更强大。
只需确保正确启用它,特别是在 Ubuntu 22.04 上,您需要:
或者要学习使用 apport,另请参阅:https://askubuntu.com/questions/1349047/where-do-i-find -core-dump-files-and-how-do-i-view-and-analyze-the-backtrace-st/1442665#1442665
My best async signal safe attempt so far
Let me know if it is not actually safe. I could not yet find a way to show line numbers.
stacktrace_on_signal_safe.cpp
Compile and run:
-rdynamic
is needed to get the function names:We can then pipe it to
c++filt
to demangle:giving:
Several levels are missing due to optimizations, with
-O0
we get a fuller:Line numbers are not present, but we can get them with
addr2line
. This requires building without-rdynamic
:producing:
awk
parses the+<addr>
numbers out o the non-rdynamic
output:If you also want to print the actual signal number to stdout, here's an async signal safe implementation int to string: Print int from signal handler using write or async-safe functions since
printf
is not.Tested on Ubuntu 22.04.
C++23
<stacktrace>
Like many other answers, this section ignores async signal safe aspects of the problem, which could lead your code to deadlock on crash, which could be serious. We can only hope one day the C++ standard will add a
boost::stacktrace::safe_dump_to
-like function to solve this once and for all.This will be the generally superior C++ stacktrace option moving forward as mentioned at: How to print a stack trace whenever a certain function is called as it shows line numbers and does demangling for us automatically.
stacktrace_on_signal.cpp
Compile and run:
Output on GCC 12.1 compiled from source, Ubuntu 22.04:
I think it missed
my_func_1
due to optimization being turned on, and there is in general nothing we can do about that AFAIK. With-O0
instead it is better:but not sure why
main
didn't show up there.backtrace_simple
https://github.com/gcc-mirror/gcc/blob/releases/gcc-12.1.0/libstdc%2B%2B-v3/src/libbacktrace/backtrace-supported.h.in#L45 mentions that
backtrace_simple
is safe:but it does not appear very convenient for usage, mostly an internal tool.
std::basic_stacktrace
This is what
std::stacktrace
is based on according to: https://en.cppreference.com/w/cpp/utility/basic_stacktraceIt has an allocator parameter which cppreference describes as:
so I wonder if
basic_stacktrace
is itself async signal safe, and if it wouldn't be possible to make a version ofstd::stacktrace
that is also with a custom allocator, e.g. either something that:boost::stacktrace::safe_dump_to
https://apolukhin.github.io/papers/stacktrace_r1.html might be the proposal that got in, mentions:
Just getting the core dump instead?
The core dump allows you to inspect memory with GDB: How do I analyze a program's core dump file with GDB when it has command-line parameters? so it is more powerful than just having the trace.
Just make sure you enable it properly, notably on Ubuntu 22.04 you need:
or to learn to use apport, see also: https://askubuntu.com/questions/1349047/where-do-i-find-core-dump-files-and-how-do-i-view-and-analyze-the-backtrace-st/1442665#1442665
对于 Linux 和 Mac OS X,如果您使用 gcc 或任何使用 glibc 的编译器,则可以使用 execinfo.h 中的 backtrace() 函数来打印堆栈跟踪并在以下情况下正常退出:你会遇到分段错误。 文档可以在libc 手册中找到。
下面是一个示例程序,它安装
SIGSEGV
处理程序,并在出现段错误时将堆栈跟踪打印到stderr
。 这里的baz()
函数会导致触发处理程序的段错误:使用
-g -rdynamic
进行编译会在输出中获取符号信息,glibc 可以使用它来制作一个漂亮的符号信息。 stacktrace:执行此命令会得到以下输出:
这显示了堆栈中每个帧来自的加载模块、偏移量和函数。 在这里,您可以看到堆栈顶部的信号处理程序,以及
main
之前的 libc 函数以及main
、foo
、酒吧
和baz
。For Linux and I believe Mac OS X, if you're using gcc, or any compiler that uses glibc, you can use the backtrace() functions in
execinfo.h
to print a stacktrace and exit gracefully when you get a segmentation fault. Documentation can be found in the libc manual.Here's an example program that installs a
SIGSEGV
handler and prints a stacktrace tostderr
when it segfaults. Thebaz()
function here causes the segfault that triggers the handler:Compiling with
-g -rdynamic
gets you symbol info in your output, which glibc can use to make a nice stacktrace:Executing this gets you this output:
This shows the load module, offset, and function that each frame in the stack came from. Here you can see the signal handler on top of the stack, and the libc functions before
main
in addition tomain
,foo
,bar
, andbaz
.它甚至比“man backtrace”更容易,有一个文档很少的库(特定于 GNU)与 glibc 一起分发为 libSegFault.so,我相信它是由 Ulrich Drepper 编写的,用于支持程序 catchsegv(请参阅“man catchsegv”)。
这给了我们3种可能性。 而不是运行“program -o hai”:
在 catchsegv 中运行:
在运行时与 libSegFault 链接:
在编译时与 libSegFault 链接:
在所有 3 种情况下,您将通过较少的优化(gcc -O0 或 -O1)和调试符号(gcc -g)获得更清晰的回溯。 否则,您最终可能会得到一堆内存地址。
您还可以通过以下方式捕获更多堆栈跟踪信号:
输出将如下所示(请注意底部的回溯):
如果您想了解详细信息,不幸的是,最好的源是源:请参阅 http://sourceware.org/git/?p= glibc.git;a=blob;f=debug/segfault.c 及其父目录 http://sourceware.org/git/?p=glibc.git;a=tree;f=debug
It's even easier than "man backtrace", there's a little-documented library (GNU specific) distributed with glibc as libSegFault.so, which was I believe was written by Ulrich Drepper to support the program catchsegv (see "man catchsegv").
This gives us 3 possibilities. Instead of running "program -o hai":
Run within catchsegv:
Link with libSegFault at runtime:
Link with libSegFault at compile time:
In all 3 cases, you will get clearer backtraces with less optimization (gcc -O0 or -O1) and debugging symbols (gcc -g). Otherwise, you may just end up with a pile of memory addresses.
You can also catch more signals for stack traces with something like:
The output will look something like this (notice the backtrace at the bottom):
If you want to know the gory details, the best source is unfortunately the source: See http://sourceware.org/git/?p=glibc.git;a=blob;f=debug/segfault.c and its parent directory http://sourceware.org/git/?p=glibc.git;a=tree;f=debug
Linux
虽然使用 execinfo.h 中的 backtrace() 函数来打印堆栈跟踪并在出现分段错误时正常退出,但 已经被建议,我没有看到任何提及确保生成的回溯指向实际位置所需的复杂性错误(至少对于某些架构 - x86 和 ARM)。
当您进入信号处理程序时,堆栈帧链中的前两个条目包含信号处理程序内部的返回地址和 libc 中 sigaction() 内部的一个返回地址。 信号之前调用的最后一个函数的堆栈帧(即故障位置)丢失。
代码
输出
在信号处理程序中调用 backtrace() 函数的所有危险仍然存在,不应被忽视,但我发现这里描述的功能对于调试崩溃非常有帮助。
值得注意的是,我提供的示例是在 Linux x86 上开发/测试的。 我还在 ARM 上使用
uc_mcontext.arm_pc
而不是uc_mcontext.eip
成功实现了这一点。这是我了解此实现的详细信息的文章的链接:
http://www.linuxjournal.com/article/6391
Linux
While the use of the backtrace() functions in execinfo.h to print a stacktrace and exit gracefully when you get a segmentation fault has already been suggested, I see no mention of the intricacies necessary to ensure the resulting backtrace points to the actual location of the fault (at least for some architectures - x86 & ARM).
The first two entries in the stack frame chain when you get into the signal handler contain a return address inside the signal handler and one inside sigaction() in libc. The stack frame of the last function called before the signal (which is the location of the fault) is lost.
Code
Output
All the hazards of calling the backtrace() functions in a signal handler still exist and should not be overlooked, but I find the functionality I described here quite helpful in debugging crashes.
It is important to note that the example I provided is developed/tested on Linux for x86. I have also successfully implemented this on ARM using
uc_mcontext.arm_pc
instead ofuc_mcontext.eip
.Here's a link to the article where I learned the details for this implementation:
http://www.linuxjournal.com/article/6391
即使正确答案< /a> 已提供,描述如何使用 GNU libc
backtrace()
函数1,我提供了 我自己的答案描述了如何确保信号处理程序的回溯指向故障的实际位置2,我没有看到任何提及demangling< /a> 回溯的 C++ 符号输出。从 C++ 程序获取回溯时,可以通过
c++filt
1 运行输出来对符号进行解调,或者使用abi::__cxa_demangle
1 直接。请注意,
c++filt
和__cxa_demangle
是 GCC 特定的以下 C++ Linux 示例使用相同的信号处理程序作为我的其他答案< /a> 并演示如何使用
c++filt
来对符号进行分解。代码:
输出 (
./test
):分解输出 (
./test 2>& 1 | c++filt
):以下内容基于我的 原始答案并且可以替换上面示例中的信号处理程序以演示如何
abi::__cxa_demangle
可用于对符号进行分解。 该信号处理程序产生与上面示例相同的分解输出。代码:
Even though a correct answer has been provided that describes how to use the GNU libc
backtrace()
function1 and I provided my own answer that describes how to ensure a backtrace from a signal handler points to the actual location of the fault2, I don't see any mention of demangling C++ symbols output from the backtrace.When obtaining backtraces from a C++ program, the output can be run through
c++filt
1 to demangle the symbols or by usingabi::__cxa_demangle
1 directly.Note that
c++filt
and__cxa_demangle
are GCC specificThe following C++ Linux example uses the same signal handler as my other answer and demonstrates how
c++filt
can be used to demangle the symbols.Code:
Output (
./test
):Demangled Output (
./test 2>&1 | c++filt
):The following builds on the signal handler from my original answer and can replace the signal handler in the above example to demonstrate how
abi::__cxa_demangle
can be used to demangle the symbols. This signal handler produces the same demangled output as the above example.Code:
您没有指定您的操作系统,因此很难回答。 如果您使用的是基于 gnu libc 的系统,您也许可以使用 libc 函数
backtrace()
。GCC 还有两个内置函数可以帮助您,但它们可能会也可能不会在您的架构上完全实现,它们是 __builtin_frame_address 和
__builtin_return_address
。 两者都需要立即整数级别(立即,我的意思是它不能是变量)。 如果给定级别的 __builtin_frame_address 不为零,则可以安全地获取同一级别的返回地址。You did not specify your operating system, so this is difficult to answer. If you are using a system based on gnu libc, you might be able to use the libc function
backtrace()
.GCC also has two builtins that can assist you, but which may or may not be implemented fully on your architecture, and those are
__builtin_frame_address
and__builtin_return_address
. Both of which want an immediate integer level (by immediate, I mean it can't be a variable). If__builtin_frame_address
for a given level is non-zero, it should be safe to grab the return address of the same level.需要注意的是,一旦生成了 core 文件,您就需要使用 gdb 工具来查看它。 为了使 gdb 理解您的核心文件,您必须告诉 gcc 使用调试符号来检测二进制文件:为此,您可以使用 -g 标志进行编译:
然后,您可以设置“ulimit -c unlimited”以让它转储一个核心,或者只是在 gdb 中运行你的程序。 我更喜欢第二种方法:
我希望这会有所帮助。
It's important to note that once you generate a core file you'll need to use the gdb tool to look at it. For gdb to make sense of your core file, you must tell gcc to instrument the binary with debugging symbols: to do this, you compile with the -g flag:
Then, you can either set "ulimit -c unlimited" to let it dump a core, or just run your program inside gdb. I like the second approach more:
I hope this helps.
感谢热情的极客让我注意到 addr2line 实用程序。
我编写了一个快速而肮脏的脚本来处理此处提供的答案的输出:
(非常感谢 jschmier!)使用 addr2line 实用程序。
该脚本接受一个参数:包含 jschmier 实用程序输出的文件的名称。
对于跟踪的每个级别,输出应打印如下内容:
代码:
Thank you to enthusiasticgeek for drawing my attention to the addr2line utility.
I've written a quick and dirty script to process the output of the answer provided here:
(much thanks to jschmier!) using the addr2line utility.
The script accepts a single argument: The name of the file containing the output from jschmier's utility.
The output should print something like the following for each level of the trace:
Code:
ulimit -c
设置 unix 上的核心文件大小限制。 默认情况下,核心文件大小限制为 0。您可以使用ulimit -a
查看您的ulimit
值。另外,如果您从 gdb 中运行程序,它会因“分段违规”(
SIGSEGV
,通常当您访问未分配的内存时)而停止您的程序,或者您可以设置断点。ddd 和 nemiver 是 gdb 的前端,这使得新手更容易使用它。
ulimit -c <value>
sets the core file size limit on unix. By default, the core file size limit is 0. You can see yourulimit
values withulimit -a
.also, if you run your program from within gdb, it will halt your program on "segmentation violations" (
SIGSEGV
, generally when you accessed a piece of memory that you hadn't allocated) or you can set breakpoints.ddd and nemiver are front-ends for gdb which make working with it much easier for the novice.
看起来在最后一个 C++ boost 版本之一中出现的库正好提供了您想要的内容,可能代码是多平台的。
它是 boost::stacktrace,您可以使用就像 如 boost 示例:
在 Linux 中,您编译上面的代码:
从 boost 文档复制的示例回溯一个>:
It looks like in one of last c++ boost version appeared library to provide exactly what You want, probably the code would be multiplatform.
It is boost::stacktrace, which You can use like as in boost sample:
In Linux You compile the code above:
Example backtrace copied from boost documentation:
城里的新国王已经到来
https://github.com/bombela/backward-cpp
1 个要放置在代码中的标头1 个要安装的库。
我个人使用这个函数来称呼它
The new king in town has arrived
https://github.com/bombela/backward-cpp
1 header to place in your code and 1 library to install.
Personally I call it using this function
我已经研究这个问题有一段时间了。
并深埋在 Google 性能工具自述文件
http://code 中。 google.com/p/google-perftools/source/browse/trunk/README
讨论 libunwind
http: //www.nongnu.org/libunwind/
很想听听这个库的意见。
-rdynamic 的问题在于,在某些情况下它会相对显着地增加二进制文件的大小
Ive been looking at this problem for a while.
And buried deep in the Google Performance Tools README
http://code.google.com/p/google-perftools/source/browse/trunk/README
talks about libunwind
http://www.nongnu.org/libunwind/
Would love to hear opinions of this library.
The problem with -rdynamic is that it can increase the size of the binary relatively significantly in some cases
您可以使用 DeathHandler - 小型 C++ 类,它可以为您完成所有操作,可靠。
You can use DeathHandler - small C++ class which does everything for you, reliable.
忘记更改源代码并使用 backtrace() 函数或宏进行一些修改 - 这些只是糟糕的解决方案。
作为一个正常工作的解决方案,我建议:
这将以人类可读的方式打印程序的正确可读回溯(带有源文件名和行号)。
此外,这种方法将使您可以自由地实现系统自动化:
有一个简短的脚本来检查进程是否创建了核心转储,然后通过电子邮件将回溯发送给开发人员,或将其记录到某些日志系统中。
Forget about changing your sources and do some hacks with backtrace() function or macroses - these are just poor solutions.
As a properly working solution, I would advice:
This will print proper readable backtrace of your program in human readable way (with source file names and line numbers).
Moreover this approach will give you freedom to automatize your system:
have a short script that checks if process created a core dump, and then send backtraces by email to developers, or log this into some logging system.