如果我从 shell 运行一个程序,并且它发生段错误:
$ buggy_program
Segmentation fault
但是,它会告诉我是否有办法让程序打印回溯,也许可以通过运行如下命令:
$ print_backtrace_if_segfault buggy_program
Segfault in main.c:35
(rest of the backtrace)
我也不想使用 strace 或 ltrace 来获取此类信息,因为它们无论如何都会打印……
答案1
可能有更好的方法,但是这种方法可以实现自动化。
输入以下内容~/backtrace
:
backtrace
quit
seg_wrapper.sh
将其放入路径目录中调用的脚本中:
#!/bin/bash
ulimit -c unlimited
"$@"
if [[ $? -eq 139 ]]; then
gdb -q $1 core -x ~/backtrace
fi
该ulimit
命令使得核心被转储。"$@"
是给脚本的参数,所以它将是你的程序及其参数。$?
保存退出状态,139 似乎是我的机器出现段错误的默认退出状态。
对于gdb
,-q
表示安静(没有介绍信息),并-x
告诉gdb
执行给它的文件中的命令。
用法
因此要使用它你只需:
seg_wrapper.sh ./mycommand and its arguments
更新
您还可以编写一个信号处理程序来执行此操作,请参阅此链接。
答案2
编辑:
在我放弃这个答案 10 年后,该功能已被弃用。因此,如果您发现您的系统/目标没有libSegFault.so
寻求替代方案。
看犯罪
很抱歉两年后才来到这里……在寻找其他东西时偶然发现了它。为了完整性,我添加了它。
- 虽然我认为接受的答案很棒,但它需要 gdb。我熟悉的方法是使用 libSegFault.so。
如果你使用以下命令运行应用程序
LD_PRELOAD=...路径到.../libSegFault.so myapp
您将获得一份包含回溯、已加载库等内容的报告
- 还有一个包装脚本
catchsegv
可用,它会尝试将addr2line
地址转换为文件名+行号。
这些是比核心文件或 gdb 更轻量的解决方案(例如适用于嵌入式系统)
答案3
答案4
Ubuntu(作为一个项目)使用 Apport 来实现这一点。你可以看看他们是如何做到的。