15

每当我的进程崩溃时,我想创建一个核心转储。目前我正在遵循这种方法:

  1. 使用 gcc/g++ 的“-g”构建程序的特殊“调试”版本。
  2. 执行“ulimit -c 无限制”
  3. 现在,每当程序崩溃时,我们都会得到核心转储。

但我想尽量减少步骤数,以便:

  • 应该始终创建核心转储。即使它是“发布”构建。不应要求用户ulimit -c unlimited手动执行命令“”。
  • 该核心转储的回溯应该能够提供调用的文件、函数、行号。那是人类可读形式的堆栈跟踪。
  • 我不想将程序构建为带有“-g”的调试版本。或者至少它不应该包含生成人类可读堆栈跟踪不需要的任何其他调试信息。因为这将是该程序的发布版本。

所以我有两个问题:

  1. 如何在程序的“发布”版本中创建核心转储?
  2. 总是。无需手动执行“ ulimit -c unlimited
4

5 回答 5

11
  • 关于核心限制,您可以在 C 中通过调用setrlimit.
  • backtrace在 GNU (glibc) 或 BSD 系统上,您可以通过调用和相关的系统调用来获得回溯。然后,您必须通过运行addr2line(或复制其功能)将函数地址转换为函数名称。
  • 只是不要使用-g,您仍然可以获得回溯(除了不会出现内联函数)。
于 2010-02-12T11:30:23.170 回答
7

通常的解决方案是使用 -g 构建并在发布文件之前剥离调试信息。寻找“剥离”命令。您保留带有调试信息的文件,并使用它来调试您从客户那里获得的核心转储。

如果你想在用户机器上打印人类可读的回溯,你需要分发带有(一些)调试信息的二进制文件。在 glibc 中寻找 'backtrace()' 函数。

请注意,即使您的二进制文件不包含调试信息,也会创建核心转储(如果 ulimit 设置得当)。

确保创建核心转储的最佳方法可能是在运行二进制文件之前从设置 ulimit 的脚本执行二进制文件。

于 2010-02-12T11:27:47.143 回答
3

你可以试试 google-coredumper:

一个从多线程应用程序创建 GDB 可读核心转储的简洁工具——在程序运行时。coredumper 库可以编译到应用程序中以创建正在运行的程序的核心转储,而无需终止。

http://sourceforge.net/projects/goog-coredumper/

于 2010-02-12T12:16:56.827 回答
2
  1. Linux 上没有“发布”版本和“调试”版本。使用“-g”时,您只需构建一个带有调试信息的程序。您可以剥离此信息。

更新
实际上,我想我应该谈谈我在消息中没有提到的调试版本和发布版本之间可能存在的一个区别。发布版本可能会使用 NDEBUG 定义来构建,以便摆脱assert()程序中的所有内容。相反,调试版本应该在不定义 NDEBUG 的情况下构建,以assert()帮助发现错误。

但是,如果您不使用assert(),则不会有任何区别。

  1. 用户可以在他或她的个人资料中设置 ulimit -c unlimited。

  2. 通过一些优化编译的程序的回溯通常不会给出有用的行号。

  3. 您可以构建带有调试信息的版本并放入存档中。然后剥离它并将剥离的二进制文件交付给您的客户。如果客户给你一个核心文件,那么只需使用带有调试信息的版本和客户提供的核心文件。

  4. How to create a core dump in the "release" build of a program?这不是你的责任,而是操作系统的责任。

于 2010-02-12T11:31:56.130 回答
-4

如果代码是发布模式/高度优化的版本,您将很难获得像样的人类形式的堆栈跟踪。使用 -g 开关或完全忘记执行堆栈跟踪......你不能同时拥有!这又回到了这一点-听起来您甚至在生产环境中也预计代码会崩溃???

你为什么不修复代码并确保它首先工作......代码气味......嗅嗅嗅觉

编辑:好的,我在上面的评论中可能有点苛刻,我不打算在那里苛刻......为了读者的利益,我已经包含了一个链接到另一个发布在这里的问题,并且在那个答案中我给了,使用信号来创建堆栈跟踪并重定向到文件。这将对OP的问题有所帮助,并帮助他进行故障排除...

于 2010-02-12T11:27:52.960 回答