【问题标题】:Try/Catch a segmentation fault on Linux在 Linux 上尝试/捕获分段错误
【发布时间】:2010-10-05 15:14:28
【问题描述】:

我有一个 Linux C++ 应用程序,我想在取消引用之前测试一个对象指针的有效性。但是由于分段错误,try/catch 在 Linux 上对此不起作用。如何做到这一点?

【问题讨论】:

    标签: c++ linux pointers segmentation-fault


    【解决方案1】:

    如果您的应用程序中的许多指针引用相同的有限生命周期对象,则一种流行的解决方案是使用boost smart pointers编辑:在 C++11 中,这两种类型都在标准库中可用

    您可能希望将shared_ptr 用于负责对象生命周期的指针,而将weak_ptr 用于其他可能无效的指针。您会看到 weak_ptr 具有您要求的内置有效性检查。

    【讨论】:

    • 我没有使用 shared_prt 但据我了解它是一个控制对象生命周期的指针。我有相反的情况。我有一个可以在收到消息后自行删除的对象。我需要那些指向它的人有办法知道他们拥有无效的指针。
    • 这正是weak_ptr 的用途。如果您稍后尝试通过weak_ptr 访问该对象,weak_ptr 将使对象死亡,并报告无效。比捕获 SIGSEGV 更好的解决方案!
    • 我认为你的情况就是这样。 “删除我”消息应该重置唯一的 shared_ptr。之后,所有由该 shared_ptr 生成的weak_ptr 都将知道它们是无效的。看一下weak_ptr链接的例子。
    【解决方案2】:

    分段错误不是异常(如 Java 的 NullPointerException);它是从操作系统发送到进程的信号。查看the manpage for sigaction 以获取有关如何为分段错误 (SIGSEGV) 安装处理程序的指示。

    【讨论】:

      【解决方案3】:

      您可以针对这一情况启用 SIGSEGV 的信号处理程序。有关详细信息,请参见手册页“信号”。另一种选择是使用保证有效的引用。当然,这取决于您的应用。

      【讨论】:

      • 手册页说如果忽略 SIGSEGV,进程状态是未定义的。捕获 SIGSEGV 后可以恢复 C++ 应用程序吗?
      • 好问题 - 可能不安全。我认为如果您担心有效性,通常最好使用引用而不是指针。正如其他发帖人指出的那样,您可以记录错误发生的位置并进行更正。
      • 引用也不保证有效。如果被引用对象的生命周期在使用引用之前结束,则结果也是未定义的(实际上与无效指针相同)。引用不能初始化为 null,也不能重置。就是这样。
      • 是的 - 但如果您“正常”使用它们,那么它们不太可能给您带来问题。我应该更清楚一点,因为您可以设置指向任何旧垃圾的指针,但是引用(至少在开始时)更难出错。我把我的机智迟钝归咎于我令人讨厌的感冒:-(。
      【解决方案4】:

      将指针初始化为 NULL。如果经过处理后仍然为NULL,则无效,否则有效。

      【讨论】:

      • 如果我删除一个对象,它的指针不是 NULL,而是指向无效的内存。如何验证这样的指针?
      • 你到底为什么要这么做?你把它删了。如果您在任何地方使用指针并且不确定它们是否被删除,那么您做的事情非常错误。
      • 我同意这一点。无效指针是无效指针。要么之后指针变量不再可访问,要么将其设置为 0。或者,因为这是 C++,所以了解 RAII。
      【解决方案5】:

      对于原始 C++ 指针,没有自然、通用的方法。 C++ 假定您将跟踪该信息。

      在大多数情况下,您可以通过记住在指针无效时将指针设置为 NULL 来处理此问题。最初不指向的新指针应设置为 NULL,新删除的对象应将其指针设置为 NULL。

      【讨论】:

        【解决方案6】:

        如何测试指针的有效性?与NULL比较?

        最好的办法是在Valgrind 下运行程序。错误可能位于完全不同的位置。

        更新:在 Win32 平台上有类似 __try __except 的东西,它允许捕获一些异常。据我所知,该 Win32 功能没有 Linux 等效功能。

        【讨论】:

        • 在 Windows 上,您可以在访问指向已释放对象的指针时捕获异常,您可以处理这种情况。在 Linux 上你会得到 SIGSEGV。我的问题是有什么方法可以验证一个指针,该指针曾经指向一个对象,因此不是 NULL 但仍被删除运算符无效。
        • 我不是 Win32 专家,但我曾经使用过 __try __except 来处理这些事情。
        • 这些是仅限 Windows 的东西,在 C++ 中暴露了平台的“结构化异常处理”(SEH)。 linux 等价物是信号......但我认为 Shmoopty 对 shared_ptr/weak_ptr 的建议更符合正确的路线。
        【解决方案7】:

        如果您将处理程序附加到 SIGSEGV,除了记录错误发生并正常失败的事实之外,您无能为力。发生此违规行为时,您的程序处于未定义状态,因此继续正常运行可能不安全。

        除了检查 NULL 之外,我不相信有一种方法可以检查指针在您所描述的意义上是否“有效”。在正常操作期间不应发生此类错误,因为它们代表错误,因此您应该希望您的程序失败,尽管是优雅的。

        【讨论】:

          【解决方案8】:

          指针存储在对象中。它们在构造函数中初始化,可能为 0 (NULL)。它们在析构函数中被删除,可能是在赋值中,很少在其他函数中。当在除析构函数之外的成员中删除时,它们会立即被分配一个新值或 0。

          【讨论】:

            【解决方案9】:

            一般来说,关于“检查非 NULL 指针的有效性”这个非常奇怪的想法,看看这篇文章:http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx(“IsBadXxxPtr 真的应该被称为 CrashProgramRandomly”)

            【讨论】:

              猜你喜欢
              • 2022-06-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-10-30
              • 1970-01-01
              • 1970-01-01
              • 2012-10-10
              相关资源
              最近更新 更多