从.NET代码中破坏非托管对象

时间:2011-09-27 20:22:03

标签: .net c++-cli unmanaged managed

我写了一个C ++库,它通过C ++ / CLI包装器暴露给我的VB.NET应用程序。

我担心通过包装器我正在穿梭于VB.NET应用程序的对象。为了使用库中的类,我为它们编写了包装器,包装器类包含指向该类的非托管实例的指针。在包装类的析构函数中,我删除了非托管指针指向的内存。

如果包装的.NET库将其中一个类实例传递给VB.NET应用程序,并且VB.NET应用程序使用它并继续(不保存对它的引用); .NET垃圾收集器是否会出现并处理此类实例导致非托管内存在类的析构函数中被释放?如果我引用了包装类实例所指向的相同内存,则会导致错误。

如果是这种情况,那么我将只复制包装器中的所有数据,以确保我的包装器不与库的本机部分共享任何数据。如果不是这种情况,那么我是否必须在包装的类实例上调用某种dispose方法来破坏非托管对象?

2 个答案:

答案 0 :(得分:1)

在CLI中,您只需使用析构函数语法(~MyClass()),C ++ / CLI编译器将为您在类上创建IDisposable实现。

在非托管代码中调用Dispose method时,将调用此“析构函数”(它不是真的,只有一个语法)。在这里你可以拨打你需要进行的调用以释放资源。

如果要实现终结器,则可以使用新的析构函数语法(!MyClass())。这应该释放与“析构函数”中相同的资源。

最后,在您的托管代码中,您只需引用IDisposable实现,然后在其上调用Dispose,而不仅仅是using statement

答案 1 :(得分:0)

你混合了一下。是的,在vb.net代码停止引用您的一个C ++ / CLI类之后,最终将在收集对象后调用终结器。请注意,这是终结器,它与dispose无关。您的C ++ / CLI对象应提供析构函数(由Dispose()调用)和终结器。

否则没有内存损坏的危险。只有当垃圾收集器找不到对象的任何实时引用时才会调用终结器。由于没有引用,因此您无法意外访问已删除的本机对象。检查this answer是否有标准模式。