Linux中的内核转储

Linux中的内核转储,linux,gcc,crash,crash-dumps,coredump,Linux,Gcc,Crash,Crash Dumps,Coredump,我想在进程崩溃时创建一个核心转储。目前,我正在采用这种方法: 使用gcc/g++的“-g”构建程序的特殊“调试”版本 执行“ulimit-c unlimited” 现在,每当程序崩溃时,我们都会得到内核转储 但我想尽量减少步骤的数量,以便: 应该始终创建核心转储。即使是“发布”版本。不应要求用户手动执行命令“ulimit-c unlimited” 该核心转储的回溯应该能够给出调用的文件、函数和行号。这是人类可读形式的堆栈跟踪 我不想用“-g”作为调试版本构建程序。或者至少它不应该包含任何其他调

我想在进程崩溃时创建一个核心转储。目前,我正在采用这种方法:

  • 使用gcc/g++的“-g”构建程序的特殊“调试”版本
  • 执行“ulimit-c unlimited”
  • 现在,每当程序崩溃时,我们都会得到内核转储
  • 但我想尽量减少步骤的数量,以便:

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

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

  • 通常的解决方案是使用-g构建,并在发布文件之前删除调试信息。查找“strip”命令。 您可以使用调试信息保存该文件,并使用它调试从客户处获得的核心转储

    如果要在用户计算机上打印人类可读的回溯,则需要分发包含(一些)调试信息的二进制文件。 在glibc中查找“backtrace()”函数

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


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

    如果代码是发布模式/高度优化的版本,则很难获得良好的人形堆栈跟踪。使用-g开关或完全忘记执行stacktrace…这两者都不能同时使用!!这又回到了这一点——听起来您甚至预期代码会在生产环境中崩溃

    为什么不先修复代码并确保它正常工作……代码有味道。。。。嗅嗅

    编辑:好的,我可能在上面的评论中遇到了一些苛刻的问题,我不打算在那里苛刻……为了读者的利益,我在这里添加了一个指向另一个问题的链接,我给出了一个链接,使用信号创建堆栈跟踪并重定向到一个文件。这将有助于OP的问题并帮助他排除故障…

    • 关于核心限制,您可以自己在C中调用
    • 在GNU(glibc)或BSD系统上,您可以通过调用和相关的系统调用获得回溯。然后,您必须通过运行
      addr2line
      (或复制其功能)将函数地址转换为函数名称
    • 只要不使用
      -g
      ,您仍然可以得到回溯(除非内联函数不会出现)
  • Linux上没有“发布”版本和“调试”版本。使用“-g”时,您只需使用调试信息构建一个程序。你可以删除这些信息
  • 更新
    实际上,我想我应该说一下调试版本和发布版本之间的一个可能的区别,我在我的消息中没有提到。发布版本可以使用NDEBUG define构建,以消除程序中的所有
    assert()
    。相反,应该在不将NDEBUG定义为
    assert()
    有助于查找bug的情况下构建调试版本。

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

  • 用户可以在其个人资料中设置ulimit-c unlimited

  • 使用某些优化编译的程序的回溯通常不会给出有用的行号

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

  • 如何在程序的“发布”版本中创建核心转储?
    这不是您的责任,而是操作系统的责任


  • 您可以尝试google coredumper:

    一个整洁的工具,用于在程序运行时从多线程应用程序创建GDB可读的CoreDump。coredumper库可以编译成应用程序来创建运行程序的核心转储,而无需终止。


    重要的是要理解'-g'和优化级别是完全不相关的。'-g'表示调试信息将添加到二进制文件中。这并不意味着代码不会得到优化。”“gcc-g-O3…”是一个非常合理的做法(需要理解的是,代码可能更难调试)。而且bug并不总是可以预测的,对吗?那一次我不想丢失信息。即使进行了优化,堆栈跟踪通常似乎给出了正确的函数(如果不一定是正确的行)。通常离这里不远。至少这是我的经验。@Kristof:我当然理解,但使用-g开关进行堆栈跟踪会让您获得真正的好处。绝对同意!这将更难解决@Sabya,@MarkR:没关系……有时,特别是作为守护进程的进程,甚至很难跟踪崩溃-资源、内存不足/耗尽,不关闭套接字等等……看看这里的代码…-它可能会帮助你。。。