【问题标题】:Unable to catch c++ exception using catch (...)无法使用 catch (...) 捕获 c++ 异常
【发布时间】:2009-09-03 14:21:29
【问题描述】:

我有一个有时会引发异常的第三方库。所以我决定将我的代码包装在 try/catch(...) 中,这样我就可以记录有关异常发生的信息(没有具体细节,只是它发生了。)

但由于某种原因,代码仍然崩溃。在客户端计算机上,它会严重崩溃,并且在 catch(...) 中记录异常的代码永远不会被执行。如果我在我的调试/开发机器上运行它,我会弹出询问我是否要调试的窗口。当我这样做时,它会报告 0xC0000005:访问冲突读取位置 XXX。

奇怪的是,对于旧版本的第三方库,完全相同的代码确实会捕获异常,并且会执行记录异常的代码。 (我在 VS 中验证了这一点,观察相同的情况发生。)

这是正在执行的伪代码:

pObject = pSystem->Get_pObject()
pSystem->DoSomethingThatMightDestroy_pObject();
try
{
    /*   Call to third party function that is throwing exception */
    pObject->SetValue(0);
}
catch (...)
{
    __DEBUG_LOG_POSITION__;  // A macro to log the current file line
    //  This code used to run in the older version of third-party library
    //  but the newer version just crashes before running the catch(...)
}

所以我有两个问题:

  1. 第三方编译库的方式是否发生了一些变化,以至于我的代码无法捕获异常? (是的,如果我知道要告诉他们什么,我可以让第三方进行任何必要的修复并为我重新编译。)

  2. 假设我无法让第三方修复它,我能做些什么来捕获这些异常?我在想……有什么方法可以让我确定 pObject 是否被释放?

【问题讨论】:

    标签: c++ exception exception-handling


    【解决方案1】:

    AFAIK 访问冲突不会抛出异常......至少不是标准的!

    也许捕获特定于 Windows 的“本机”异常会有所帮助:https://web.archive.org/web/20081022160935/http://www.gamedev.net/reference/articles/article2488.asp

    【讨论】:

    • 哇,这是一篇非常有用的文章,并且确实包含对我来说可行的解决方案......旧库必须在 VS2003 下构建,而新库适用于 VS2008 - 关键区别.在将我的库设置为使用选项“启用 C++ 异常:是 SEH 异常 (/EHa)”进行编译后,我的代码现在捕获了这个实例。出于这个原因,我授予此回复正确答案。但是,我想说的是,其他几个答案提供了有效的有用信息,尤其是关于“在继续……中没有多大用处”的答案,所以谢谢大家!!
    • 使用 C++ try/catch 捕获 SEH 异常通常是个坏主意。 MS 在其较新的编译器中默认禁用它是有原因的。通常,您应该使用 SEH 结构(如 __try/__except)而不是启用该编译器选项。
    • Michael Bray> 没问题,我想这里有很多答案可以帮助解决这类问题。我也会投票给其他人,以便在这个答案下弥补它们。 jalf>确实。这就是他们在文章中所做的。
    【解决方案2】:

    访问冲突不是 C++ 异常。这是一个 Windows 结构化异常。如果您想在 catch(...) 中捕获它们,则必须使用 _set_se_translator()。

    出于各种原因,您可能应该在 Google 上搜索 catch(...) 是邪恶的,并确保您确实想要这样做。

    【讨论】:

    • 这是一个很好的信息......但是,就我而言,似乎我必须在 main() 函数中使用 _set_se_translator() (至少根据文章中的示例上面的Sharptooth引用)...我没有提到的一件事是我的代码实际上是一个由另一个应用程序(实际上是第三方应用程序)加载的com对象,我无法控制main()正在使用。否则我认为这将是最好的路径。
    • 糟糕,我的意思是在 Klaim 的文章中引用。对不起!
    【解决方案3】:

    如果您在 Windows 平台上,您可以尝试查看 __try

    但是,请注意,除非您确实确定可以隔离和处理异常,否则继续执行并没有多大用处。

    【讨论】:

      【解决方案4】:

      你所描述的看起来很像 ::terminate() 正在被 C++ 运行时调用。

      这通常是由所谓的双重异常引起的——在某个地方抛出异常,堆栈展开开始,并且在堆栈展开期间调用的析构函数之一也抛出异常。在这种情况下 ::terminate() 被调用,你不能真正帮助程序。

      如果是这种情况,唯一的解决办法是获取一个新版本的库,其中不允许在析构函数之外出现异常。您可以很容易地验证它 - 在加载库后调用 ::set_terminate() 并提供您自己的函数并检查它是否在程序崩溃之前被调用。

      【讨论】:

        猜你喜欢
        • 2017-08-07
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 2013-09-30
        • 2019-08-16
        • 1970-01-01
        • 2013-12-05
        • 1970-01-01
        相关资源
        最近更新 更多