如果出现段错误,您可以在 Linux 中获得任何程序来打印堆栈跟踪吗?

Nei*_*eil 25 linux segmentation-fault

如果我从 shell 运行一个程序,它会出现段错误:

$ buggy_program
Segmentation fault
Run Code Online (Sandbox Code Playgroud)

然而,它会告诉我,有没有办法让程序打印回溯,也许是通过运行这样的东西:

$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)
Run Code Online (Sandbox Code Playgroud)

我也不想将 strace 或 ltrace 用于此类信息,因为它们会以任何一种方式打印...

Kyl*_*ndt 30

可能有更好的方法,但这种方法使其自动化。

将以下内容放入~/backtrace

backtrace
quit
Run Code Online (Sandbox Code Playgroud)

把它放在一个seg_wrapper.sh在你的路径目录中调用的脚本中:

#!/bin/bash
ulimit -c unlimited
"$@"
if [[ $? -eq 139 ]]; then
    gdb -q $1 core -x ~/backtrace
fi
Run Code Online (Sandbox Code Playgroud)

ulimit命令使得核心被转储。"$@"是提供给脚本的参数,因此它将是您的程序及其参数。$?保存退出状态,139 似乎是我的机器出现段错误的默认退出状态。

对于gdb,-q表示安静(没有介绍消息),并-x告诉gdb执行给它的文件中的命令。

用法

因此,要使用它,您只需:

seg_wrapper.sh ./mycommand and its arguments 
Run Code Online (Sandbox Code Playgroud)

更新

您还可以编写一个执行此操作的信号处理程序,请参阅此链接

  • 您与信号处理程序解决方案的链接已失效-这就是答案不应链接到其他资源的原因... (2认同)

nhe*_*hed 23

很抱歉在 2 年后来到这里......在寻找其他东西时偶然发现。添加这个是为了完整性。

1)虽然我认为接受的答案很好,但它需要 gdb。我熟悉的方法使用libSegFault.so。

如果你运行你的应用程序

LD_PRELOAD=...path-to.../libSegFault.so myapp

你会得到一个带有回溯、加载的库等的报告

2)catchsegv还可以使用包装脚本,尝试addr2line将地址转换为文件名 + 行号。

这些是比核心文件或 gdb 轻得多的解决方案(例如适用于嵌入式系统)


wul*_*pro 7

catchsegv

在另一个答案中提到了它(但绝不关注)。它是与 glibc 项目捆绑在一起的一个方便的工具。只有当程序确实存在段错误时,它才会提供回溯(和其他有用的调试信息)。

这里有一篇很好的文章。

您可以根据需要将其包含在您自己的脚本中。


小智 6

你需要每个人的朋友 GDB

gdb <program> [core file]
Run Code Online (Sandbox Code Playgroud)

一旦您加载了您的核心文件,命令“backtrace”(可以缩写为 bt)将为您提供当前的调用堆栈。如果从 gdb 内部运行程序,则可以设置任意断点并检查内存内容等。