在 Visual Studio 2010 中混合异常处理模型的后果是啥?

Posted

技术标签:

【中文标题】在 Visual Studio 2010 中混合异常处理模型的后果是啥?【英文标题】:What are the consequences of mixing exception handling models in Visual Studio 2010?在 Visual Studio 2010 中混合异常处理模型的后果是什么? 【发布时间】:2011-06-29 16:45:38 【问题描述】:

我有第三方静态库,将Enable C++ Exceptions 设置为No(未指定/EH 标志)。从启用 C++ 异常 (/EHa) 构建的代码中调用它会有什么后果?如果从库中抛出结构化异常,主应用程序提供给 _set_se_translator 的函数是否会被可靠地调用? (我的实验表明它会,但只是想知道这是否是定义的行为)。

在混合/EH 异常处理模型时还有其他注意事项吗?

【问题讨论】:

从技术上讲,标准会说这会导致破坏 ODR 的未定义行为。但是,我假设您想要更具体的解释(这就是为什么这是评论)。 @Billy ONeal:一旦禁用异常,您就会点击 UB;混合不会使情况变得更糟。 UB 没有度数。 @MSalters:大声笑——甚至没有想到这一点。没错。 是的,我意识到我在这里处于非标准领域。我只是想知道微软的实现是否在这种情况下定义了行为。 【参考方案1】:

调用没有启用异常的代码应该不会产生任何问题——这与调用外部 C 函数或类似的东西没有什么不同。

调用未启用异常的 from 代码(进入启用异常的代码)可能不会在异常禁用代码中包含正确的堆栈展开语义,这意味着您将破坏该代码的不变量代码,除非它是专门为处理异常而设计的。 (例如,一些库(例如 ANTLR)在一个块中分配所有内存并让用户代码一次释放所有内容,从而允许使用异常而不会泄漏,即使它们本身不使用异常。

Raymond Chen 有一篇关于 C++ 异常处理如何在 MSVC++ 上工作的内部文章。长话短说,它建立在 Windows 的 SEH 之上。因此,它的行为应该与您在例如抛出 SEH 异常时发生的情况类似。 C 代码。 (不过,我自己没有验证过)

【讨论】:

所有 Windows 问题都会返回给 Raymond Chen。 :) 谢谢!【参考方案2】:

根据MSDN 则允许混/EHa and /EHsc:

同步和异步两种异常处理模型完全兼容,可以在同一个应用程序中混合使用。

但这条规则似乎有一个例外,那就是当将异常从非托管 (/EHsc) 传递到 managed (/clr) 时。托管代码使用结构化异常处理 (SEH) 捕获所有异常,这会在展开堆栈时导致 unmanaged destructors not to be called。有不同的解决方法:

    将非托管代码更改为使用 /EHa 而不是 /EHsc。这样做的缺点是,非托管代码中的 catch(...) 会突然捕获访问冲突和其他疯狂的东西。

    在非托管代码中创建 try-catch 块,并确保在非托管世界和托管世界之间没有异常传递。

    2.1。可能的中间道路是确保在将异常从非托管世界传递到托管世界时不会调用任何析构函数。在非托管代码中创建一个 try-catch 包装器,然后在 catch-block 中将异常重新抛出到托管世界中。

【讨论】:

关于托管非托管交互的详细解释的好答案。您能否详细说明为什么在链接已过期的情况下不调用析构函数?我想当异常捕获端期望 SEH 样式异常而抛出端使用 C++ 异常时,堆栈展开 thunk 对捕获端变得有点“不可见”?

以上是关于在 Visual Studio 2010 中混合异常处理模型的后果是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2010 总是认为项目已过时,但没有任何改变

在 Windows 7 而不是 Windows XP 上运行 Visual Studio 2010 的优势

Visual Studio 2010——如何减少其内存占用

在 Visual Studio 和 VIM 中强制编码样式

适用于 Visual Studio 2015 的混合

如何在 Visual Studio 2012 速成版附带的混合中制作 wpf 应用程序