从 .NET 代码中销毁非托管对象
我编写了一个 C++ 库,通过 C++/CLI 包装器向我的 VB.NET 应用程序公开该库。
我担心通过包装器传送到 VB.NET 应用程序的对象。为了使用库中的类,我为它们编写了包装器,并且包装器类包含指向该类的非托管实例的指针。在包装类的析构函数中,我删除了非托管指针指向的内存。
如果包装的 .NET 库将这些类实例之一传递给 VB.NET 应用程序,并且 VB.NET 应用程序使用它并继续前进(不保存对其的引用); .NET 垃圾收集器会出现并处置此类实例,导致非托管内存在类的析构函数中被释放吗?如果我引用了包装类实例所指向的同一内存,这将导致错误。
如果是这种情况,那么我将复制包装器中的所有数据,以确保我的包装器不会与库的本机部分共享任何数据。如果不是这种情况,那么我是否必须在包装的类实例上调用某种 dispose 方法才能销毁非托管对象?
I've wrote a C++ library that is exposed to my VB.NET application through a C++/CLI wrapper.
I'm worried about objects that I'm shuttling up to the VB.NET application through the wrapper. To use the classes in the library I've written wrappers for them and the wrapper classes contain pointers to an unmanaged instance of the class. In the destructor of the wrapper class I delete the memory that the unmanaged pointer is pointing to.
If the wrapped .NET library passes one of these class instances to the VB.NET application and the VB.NET application uses it and moves on (doesn't save a reference to it); will the .NET garbage collector come around and dispose this class instance causing the unmanaged memory to be deallocated in the destructor of the class? This would cause an error if I had a reference to this same memory that the wrapped class instance pointed to.
If this is the case then I'll just copy all the data in the wrapper to ensure that my wrappers don't share any data with the native portion of the library. If this isn't the case then do I have to call some sort of dispose method on the wrapped class instance in order to destruct the unmanaged object?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 CLI 中,您只需使用析构函数语法 (
~MyClass()
),C++/CLI 编译器就会创建一个IDisposable
为您实现该类。当
Dispose
方法 在非托管代码中调用。您可以在此处放置释放资源所需的调用。如果您想实现终结器,那么您将使用新的析构函数语法 (
!MyClass()
)。这应该释放与“析构函数”中相同的资源。最后,在托管代码中,您只需引用
IDisposable
实现,然后对其调用Dispose
,很可能通过using
语句。In CLI, you simply have to use the destructor syntax (
~MyClass()
) and the C++/CLI compiler will create anIDisposable
implementation on the class for you.This "destructor" (it's not really, it just has the syntax of one) will be called when the
Dispose
method is called in unmanaged code. It's here that you would put the calls you need to make in order to release resources.If you want to implement a finalizer, then you would use the new destructor syntax (
!MyClass()
). This should release the same resources that you would in your "destructor".Finally, in your managed code, you simply would reference the
IDisposable
implementation and then callDispose
on it, more than likely through theusing
statement.你把它搞混了一点。是的,在 vb.net 代码停止引用 C++/CLI 类之一之后,最终将在收集对象后调用终结器。请注意,这是终结器,它与 dispose 无关。您的 C++/CLI 对象应提供析构函数(由 Dispose() 调用)和终结器。
否则不存在内存损坏的危险。仅当垃圾收集器找不到对该对象的任何实时引用时,才会调用终结器。由于没有留下任何引用,因此您不可能意外访问已删除的本机对象。检查此答案以获取标准模式。
You are mixing it up a bit. Yes, after the vb.net code stops referencing one of your C++/CLI classes then eventually the finalizer will be called after the object got collected. Note that this is the finalizer, it has nothing to do with dispose. Your C++/CLI object should provide both a destructor (called by Dispose()) and a finalizer.
There is otherwise no danger of memory corruption. The finalizer only gets called when the garbage collector cannot find any live references to the object. Since there is no reference left, there's no way that you can accidentally access the deleted native object. Check this answer for the standard pattern.