【问题标题】:Is there a point to trapping "segfault"?捕获“segfault”有什么意义吗?
【发布时间】:2009-12-23 21:14:41
【问题描述】:

我知道,如果有足够的上下文,人们可能希望从 segfault 条件中建设性地使用(即恢复)。

但是,这些努力值得吗?如果是,在什么情况下?

【问题讨论】:

    标签: linux segmentation-fault


    【解决方案1】:

    您不能真正希望从段错误中恢复。您可以检测到它发生了,并在可能的情况下转储出相关的特定于应用程序的状态,但您无法继续该过程。这是因为(除其他外)

    • 失败的线程无法继续,因此您唯一的选择是 longjmp 或终止线程。在大多数情况下,两者都不安全。
    • 无论哪种方式,您都可能使互斥锁/锁处于锁定状态,从而导致其他线程永远等待
    • 即使没有发生这种情况,您也可能会泄漏资源
    • 即使您不执行上述任何一项操作,发生段错误的线程也可能在失败时使应用程序的内部状态不一致。不一致的内部状态可能会导致数据错误或随后出现进一步的不良行为,从而导致比简单退出更多的问题

    因此,一般来说,捕获它并做任何事情都是没有意义的,除非以相当突然的方式终止进程。尝试将(重要)数据写回磁盘或继续做其他有用的工作是没有意义的。将状态转储到日志(许多应用程序都会这样做)然后退出是有一定意义的。

    一个可能有用的事情可能是 exec() 你自己的进程,或者有一个看门狗进程在崩溃的情况下重新启动它。 (注意:如果您的进程有 >1 个线程,则 exec 并不总是具有明确定义的行为)

    【讨论】:

    • 一个很好的总结,但我不同意我在回答中提到的原因;有时您正在执行可能导致段错误的特定操作,并且“恢复”不是问题。
    【解决方案2】:

    原因有很多:

    1. 提供更多特定于应用程序的信息以调试崩溃。例如,我在第 3 阶段处理文件“x”时崩溃了。
    2. 探测某些内存区域是否可访问。这主要是为了满足嵌入式系统的 API。我们会尝试写入内存区域并捕获告诉我们内存是只读的段错误。
    3. 段错误通常源于来自 MMU 的信号,操作系统使用该信号在必要时交换内存页。如果操作系统没有该内存页,它会将信号转发到应用程序。

    【讨论】:

      【解决方案3】:

      a Segmentation Fault 确实在访问您无权访问的内存(或者因为它没有被映射,您没有权限,虚拟地址无效等)。

      根据根本原因,您可能希望捕获并处理分段错误。例如,如果您的程序传递了一个无效的虚拟地址,它可能会记录该段错误,然后进行一些损坏控制。

      段错误不一定意味着程序堆已损坏。读取无效地址(例如空指针)可能会导致段错误,但这并不意味着堆已损坏。此外,一个应用程序可以有多个堆,具体取决于 C 运行时。

      【讨论】:

      • @kervin:什么样的损害控制?到那时堆可能是一堆垃圾
      • @Alon:编辑以解决您的问题。段错误不一定意味着堆已损坏。此外,您的处理程序不必使用受段错误影响的相同堆或地址空间。
      • 分段错误已被垃圾收集算法用于在堆末尾设置屏障,当访问时,sigsegv 被传递,这表明需要进行 gc。
      【解决方案4】:

      如果您知道分段错误不是错误,则可以通过捕获分段错误来实现非常先进的技术。例如,您可以保护页面,使您无法从中读取,然后在读取完成之前捕获 SIGSEGV 以执行“神奇”行为。 (请参阅Tomasz Węgrzanowski "Segfaulting own programs for fun and profit" 了解您可能会做什么的示例,但通常开销非常高,因此不值得这样做。)

      类似的原则适用于捕获非法指令异常(通常在内核中)以模拟未在您的处理器上实现的指令。

      【讨论】:

        【解决方案5】:

        例如,记录崩溃堆栈跟踪。

        【讨论】:

          【解决方案6】:

          没有。我认为这是浪费时间 - 段错误表明您的代码中有问题,建议您通过检查核心转储和/或源代码来找到它。有一次我试图捕获一个 seg 错误导致我进入一个镜子大厅,我可以通过简单地考虑源代码来避免这种情况。再也不会了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-09-16
            • 2010-09-23
            • 2011-07-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-04
            • 2013-07-21
            • 1970-01-01
            相关资源
            最近更新 更多