native(C ++)异常传播到CLR组件时不调用的析构函数 [英] Destructors not called when native (C++) exception propagates to CLR component

查看:271
本文介绍了native(C ++)异常传播到CLR组件时不调用的析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



然后我们有几个包含C ++ / CLI代理代码的dll,用来包装C ++接口。



除此之外,我们将C#代码调用到C ++ / CLI包装器中。



到目前为止。



但是我们有很多情况允许本机C ++异常传播到.Net世界,我们依靠.Net的能力将它们包装为系统.Exception对象大部分工作正常。



然而,我们已经发现,在throw的时候,范围内的对象的析构函数不会被调用例外传播!



经过一些研究,我们发现这是一个相当知名的问题。然而,解决方案/解决方法似乎不太一致。我们确实发现,如果本机代码与/ EHa编译而不是/ EHsc,则问题消失(至少在我们的测试用例中)。然而,我们更喜欢使用/ EHsc,因为我们自己将SEH异常转换为C ++异常,我们宁愿允许编译器更多的优化范围。



是否有其他解决方法对于这个问题 - 除了在一个(本机)try-catch-throw(除了C ++ / CLI层之外)包装每个调用跨本机管理的边界?

解决方案

/ E编译器切换的MSDN页面确实表明了这种行为: -



http://msdn.microsoft.com/en-us/library/1deeycx5(VS.80) .aspx



以下是相关报价: -


如果您使用/ EHs,那么您的catch
子句将不会捕获异步
异常。另外,在Visual C ++ 2005中,

异步异常生成时,范围内的所有对象
即使处理
异步异常也不会被销毁。


基本上/ EHsc是乐观的视图 - 它假定唯一的例外是真正的C ++风格的,并将相应地进行优化。 / EHa另一方面采取悲观的观点,并假设任何代码行都可能导致产生异常。



如果你可以保证你永远不会访问冲突或页内错误或其他SEH然后使用/ EHsc。但是如果你正在写一个服务和/或想提供一个尽力而为,那么/ EHa将是必要的。



我也同意@ JaredPar的看法关于不允许异常跨越模块边界。 @nobugz关于CLR处理异常的方式可能是真的,但我认为.Net代码使用P / Invoke直接调用本机代码并调用C ++ / CLI互操作DLL有区别。在前一种情况下,CLR必须代表您处理这种情况,而在后者中,您将受到控制并可以相应地进行转换。


We have a large body of native C++ code, compliled into DLLs.

Then we have a couple of dlls containing C++/CLI proxy code to wrap the C++ interfaces.

On top of that we have C# code calling into the C++/CLI wrappers.

Standard stuff, so far.

But we have a lot of cases where native C++ exceptions are allowed to propagate to the .Net world and we rely on .Net's ability to wrap these as System.Exception objects and for the most part this works fine.

However we have been finding that destructors of objects in scope at the point of the throw are not being invoked when the exception propagates!

After some research we found that this is a fairly well known issue. However the solutions/ workarounds seem less consistent. We did find that if the native code is compiled with /EHa instead of /EHsc the issue disappears (at least in our test case it did). However we would much prefer to use /EHsc as we translate SEH exceptions to C++ exceptions ourselves and we would rather allow the compiler more scope for optimisation.

Are there any other workarounds for this issue - other than wrapping every call across the native-managed boundary in a (native) try-catch-throw (in addition to the C++/CLI layer)?

解决方案

The MSDN page for the /E compiler switch does state this behaviour:-

http://msdn.microsoft.com/en-us/library/1deeycx5(VS.80).aspx

Here is the relevant quote:-

If you use /EHs, then your catch clause will not catch asynchronous exceptions. Also, in Visual C++ 2005, all objects in scope when the asynchronous exception is generated will not be destroyed even if the asynchronous exception is handled.

Basically /EHsc is the optimistic view - it assumes that the only exceptions are true C++ style ones and will optimise accordingly. /EHa on the other hand takes the pessimistic view and assumes that any line of code could cause an exception to be generated.

If you can guarentee that you'll never cause an Access Violation, or In-Page Error or other SEH then use /EHsc. But If you're writing a service and/or want to provide a "best effort" then /EHa is going to be necessary.

I also agree with @JaredPar's sentiments about not allowing exceptions to cross module boundaries. What @nobugz says about the way the CLR handles exceptions may be true, but I think there is a difference between .Net code calling out directly to native code using P/Invoke and calling into a C++/CLI interop DLL. In the former case the CLR has to handle the situation on your behalf, whereas in the latter you are in control and can translate accordingly.

这篇关于native(C ++)异常传播到CLR组件时不调用的析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆