Linux 中的核心转储
Posted
技术标签:
【中文标题】Linux 中的核心转储【英文标题】:Core dump in Linux 【发布时间】:2011-01-16 02:55:02 【问题描述】:我想在我的进程崩溃时创建一个核心转储。目前我正在遵循这种方法:
-
使用 gcc/g++ 的“-g”构建程序的特殊“调试”版本。
执行“ulimit -c unlimited”
现在我们在程序崩溃时获取核心转储。
但我想尽量减少步骤数,以便:
应始终创建核心转储。即使它是“发布”构建。不应要求用户手动执行命令“ulimit -c unlimited
”。
核心转储的回溯应该能够给出调用的文件、函数、行号。这是人类可读形式的堆栈跟踪。
我不想使用“-g”将程序构建为调试版本。或者至少它不应该包含生成人类可读堆栈跟踪所不需要的任何其他调试信息。因为这将是程序的发布版本。
所以我有两个问题:
-
如何在程序的“发布”版本中创建核心转储?
总是。无需手动执行“
ulimit -c unlimited
”
【问题讨论】:
【参考方案1】: 关于核心限制,您可以在 C 中通过调用setrlimit
自行完成。
在 GNU (glibc) 或 BSD 系统上,您可以通过调用 backtrace
和相关的系统调用来获得回溯。然后,您必须通过运行 addr2line
(或复制其功能)将函数地址转换为函数名称。
只是不要使用-g
,你仍然可以获得回溯(除了不会出现内联函数)。
【讨论】:
【参考方案2】:通常的解决方案是使用 -g 构建并在发布文件之前剥离调试信息。寻找“剥离”命令。 您保留包含调试信息的文件,并使用它来调试您从客户那里获得的核心转储。
如果您想在用户机器上打印人类可读的回溯,您需要分发带有(一些)调试信息的二进制文件。 在 glibc 中寻找 'backtrace()' 函数。
请注意,即使您的二进制文件不包含调试信息,也会创建核心转储(如果 ulimit 设置得当)。
确保创建核心转储的最佳方法可能是在运行二进制文件之前从设置 ulimit 的脚本执行二进制文件。
【讨论】:
【参考方案3】:你可以试试 google-coredumper:
一个从多线程应用程序创建 GDB 可读核心转储的简洁工具——在程序运行时。 coredumper 库可以编译到应用程序中以创建正在运行的程序的核心转储,而无需终止。
http://sourceforge.net/projects/goog-coredumper/
【讨论】:
【参考方案4】:-
Linux 上没有“发布”版本和“调试”版本。使用“-g”时,您只需构建一个带有调试信息的程序。您可以剥离这些信息。
更新
实际上,我认为我应该谈谈我在消息中没有提到的调试版本和发布版本之间可能存在的一个区别。发布版本可能会使用 NDEBUG 定义构建,以消除程序中的所有 assert()
。相反,应该构建调试版本而不将 NDEBUG 定义为 assert()
有助于发现错误。
但是,如果您不使用assert()
,则不会有任何区别。
用户可以在他或她的个人资料中设置 ulimit -c unlimited。
经过一些优化编译的程序的回溯通常不会给出有用的行号。
您可以构建带有调试信息的版本并放入存档中。然后剥离它并将剥离的二进制文件交付给您的客户。如果客户给你一个核心文件,那么只需使用带有调试信息的版本和客户提供的核心文件。
How to create a core dump in the "release" build of a program?
这不是你的责任,而是操作系统的责任。
【讨论】:
【参考方案5】:如果代码是发布模式/高度优化的版本,您将很难获得像样的人类形式的堆栈跟踪。使用 -g 开关或完全忘记执行堆栈跟踪......你不能同时拥有!这又回到了这一点 - 听起来您甚至在生产环境中也预计代码会崩溃???
你为什么不修复代码并确保它首先工作...代码有异味...。sniff sniff
编辑:好吧,我在上面的评论中可能有点苛刻,我并不打算在那里苛刻......为了读者的利益,我已经包含了一个链接到此处发布的另一个问题,在我给出的answer 中,使用信号创建堆栈跟踪并重定向到文件。这将有助于解决 OP 的问题并帮助他进行故障排除......
【讨论】:
理解'-g' 和优化级别完全不相关很重要。 “-g”表示调试信息将被添加到二进制文件中。这并不意味着代码不会被优化。 'gcc -g -O3 ...' 是完全合理的做法(理解代码可能稍微难以调试)。 好吧,因为有时崩溃很难重现。而且错误并不总是可以预测的,对吧?那个时候我不想丢失信息。 即使经过优化,堆栈跟踪通常似乎也能提供正确的功能(如果不一定是正确的行)。它通常不远。至少这是我的经验。 @Kristof:我当然理解这一点,但是您将获得使用 -g 开关的堆栈跟踪的真正好处。绝对同意!这将更难解决...... @Sabya,@MarkR:没关系......有时尤其是作为守护进程的进程,甚至难以追踪崩溃 - 资源匮乏/耗尽,内存,不关闭套接字等。 ..在此处查看此代码...***.com/questions/2177597/… - 它可能对您有所帮助...以上是关于Linux 中的核心转储的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的程序的核心转储在安装在 Linux 中的 NTFS 分区上运行时总是零字节?
Linux:段错误(核心已转储) Segmentation fault (core dumped)(在Linux上如何得到一个段错误的核心转储)(笔记)(未完成,暂停)