普通类型的GCHandle是否需要释放?

时间:2018-12-01 03:04:20

标签: c++ garbage-collection clr marshalling

MSDN表示

  

您还可以使用GCHandle创建固定对象,该对象返回一个   内存地址,以防止垃圾回收器移动对象   在内存中。

     

当句柄超出范围时,必须通过以下方式显式释放它:   调用Free方法;否则,可能会发生内存泄漏。当你   释放固定的句柄后,关联的对象将被取消固定并将   如果没有其他条件,就有资格进行垃圾收集   引用。

因此,如果将非固定的普通GCHandle创建到名为fooObj的托管类对象,则

GCHandle gch = GCHandle::Alloc(fooObj, GCHandleType::Normal);

是否需要使用Free()释放它?

gch.Free();

还是GC在不需要时将其释放?

我不希望释放它的原因是因为在以下代码中,即使在分配并释放了诸如gch2之类的其他GCHandle之后,我仍需要paramsArgVPtr和gch1继续引用fooObj对象。但是,似乎一旦gch2被释放,尽管gch1仍在引用该对象,但关联对象却被取消固定。无论哪种方式,gch1都会失去对该对象的访问权限。

#include "pch.h"
#include <iostream>

using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;

ref class Foo // Required to be a managed ref class
{
private:
    int a = 0;
};

int main()
{
    Foo ^ fooObj = gcnew Foo();

    // Get a void pointer that can access the object
    GCHandle gch1 = GCHandle::Alloc(fooObj, GCHandleType::Normal);
    void * paramsArgVPtr = GCHandle::ToIntPtr(gch1).ToPointer();

    // This would happen in an external non-member function that accepts a void * argument paramsArgVPtr
    // But I'm putting it here for a minimal example.
    GCHandle gch2 = GCHandle::FromIntPtr(IntPtr(paramsArgVPtr));
    Foo ^ fooObjCopy = safe_cast<Foo ^>(gch2.Target);
    gch2.Free();

    // Check to see if the object is still accessible through gch1
    if (gch1.Target == nullptr)
    {
        cout << "gch1 points to a null pointer after freeing gch2" << endl;
    }
    else
    {
        cout << "gch1 can still access the object after freeing gch2" << endl;
    }

    gch1.Free();
}

0 个答案:

没有答案