管理托管(C#)和非托管(C ++)对象的析构函数 [英] Managing destructors of managed (C#) and unmanaged (C++) objects

查看:571
本文介绍了管理托管(C#)和非托管(C ++)对象的析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个c#dll中的托管对象,它在c ++ dll中维护一个非托管对象的匿名整数句柄。在c ++ dll中,匿名整数在std :: map中用于检索非托管c ++对象。通过这个机制,我可以使用匿名整数句柄维持一个管理对象和非管理对象之间的松散关联。

I have a managed object in a c# dll that maintains an anonymous integer handle to an unmanaged object in a c++ dll. Inside the c++ dll, the anonymous integer is used in an std::map to retrieve an unmanaged c++ object. Through this mechanism, I can maintain a loose association between a managed and unmanaged object using an anonymous integer handle.

在管理对象的finalize方法(析构函数)调用非托管dll删除非托管对象。

In the finalize method (destructor) of the managed object I have a call into the unmanaged dll to delete the unmanaged object.

一切都很好,c#程序运行,但我有一个问题,当程序退出。因为我没有在被管理方的删除操作的顺序控制,非托管dll在任何被管理对象之前从内存中删除。因此,当管理对象的析构函数被调用时(它至少间接调用非托管析构函数),非托管对象已经被删除,程序崩溃。

All is well as the c# program runs, but I have a problem when the program exits. Becuase I have no control on the order of delete operations on the managed side, the unmanaged dll is deleted from memory BEFORE any managed object. Thus when the managed object's destructor is called (which in turn calls the unmanaged destructor [at least indirectly]), the unmanaged object has already been deleted and the program crashes.

所以我如何安全地删除一个外部c ++ dll中与一个管理对象关联在ac#程序中的非托管对象。

So how can I safely delete a unmanaged object in an external c++ dll that is associated with a managed object in a c# program.

感谢

Andrew

推荐答案

你可以通过检查Environment.HasShutdownStarted你的C#对象(而不是调用C ++ DLL /删除C ++对象,如果HasShutdownStarted为真)。如果你不在主AppDomain,那么你可能需要检查AppDomain.Current.IsFinalizingForUnload(实际上这可能会更安全一般)。

You may be able to solve this quickly by checking Environment.HasShutdownStarted in the finaliser of your C# object (and not calling into the C++ DLL / deleting the C++ object if HasShutdownStarted is true). If you are not in the main AppDomain then you might need to check AppDomain.Current.IsFinalizingForUnload instead (in fact this may be safer in general).

注意这只是避免调用释放的库(即避免运行非托管析构函数):如果非托管库持有在进程关闭时不会自动释放的资源,那么该资源可能泄漏。 (大多数操作系统资源在进程关闭时被释放,所以这通常不会是一个问题。)正如Adam所说,CLR终结器意在作为故障保护:你真的想要更确定地释放资源。因此,如果结构可能,Igor的建议实现IDisposable在C#类和确定性处置对象将是更可取的。

Note this merely avoids calling the freed library (i.e. avoids running the unmanaged destructor): if the unmanaged library was holding a resource that won't automatically be freed on process shutdown, then that resource could be leaked. (Most OS resources are freed on process shutdown, so this will often not be a concern.) And as Adam notes the CLR finaliser is intended as a failsafe: you really want to free resources more deterministically. Therefore, if structurally possible, Igor's suggestion to implement IDisposable on the C# class and deterministically Dispose the object would be preferable.

这篇关于管理托管(C#)和非托管(C ++)对象的析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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