我们有大量的本机 C++ 代码,已编译成 DLL。
然后我们有几个包含 C++/CLI 代理代码的 dll 来包装 C++ 接口。
最重要的是,我们有 C# 代码调用 C++/CLI 包装器。
标准的东西,到目前为止。
但在很多情况下,本机 C++ 异常被允许传播到 .Net 世界,并且我们依赖 .Net 将这些异常包装为 System.Exception 对象的能力,并且在大多数情况下这工作得很好。
然而,我们发现,当异常传播时,抛出点范围内的对象的析构函数不会被调用!
经过一些研究,我们发现这是一个众所周知的问题。然而,解决方案/解决方法似乎不太一致。我们确实发现,如果使用 /EHa 而不是 /EHsc 编译本机代码,问题就会消失(至少在我们的测试用例中是这样)。然而,我们更喜欢使用 /EHsc,因为我们自己将 SEH 异常转换为 C++ 异常,并且我们宁愿让编译器有更多的优化空间。
除了将跨本机管理边界的每个调用包装在(本机)try-catch-throw 中(除了 C++/CLI 层之外)之外,是否还有其他解决方法?
不幸的是,我不相信有任何好的解决方法。 MS 平台上的 C++ 异常实现是使用 SEH 异常 (IIRC) 来实现的。 CLR 挂钩 SEH 处理以捕获本机异常并将其处理为 CLR 异常。由于它在 SEH 级别捕获它们,因此异常看起来像 C++ 的 SEH 异常,并且析构函数相应地运行或不运行。
正如您所指出的,最好的两个选择是
- 使用 /EHa 进行编译
- 在函数的入口和出口点添加 try/catch
理想情况下,无论如何你都应该做第二个。根据我的经验,允许 C++ 异常跨越组件边界被认为是不好的做法。
您还可以使用一个 hacky 解决方案来实现_set_seh_translator
(文档 http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)。不过,我强烈建议避免使用该函数,因为它可能会无意中破坏 CLR 异常处理并导致许多不必要的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)