Нужно ли освобождать GCHandle нормального типа? - PullRequest
0 голосов
/ 01 декабря 2018

MSDN говорит, что

Вы также можете использовать GCHandle для создания закрепленного объекта, который возвращает адрес памяти, чтобы предотвратить перемещение объекта в памяти сборщиком мусора.

Когдаhandle выходит за рамки видимости, вы должны явно освободить его, вызвав метод Free;в противном случае возможны утечки памяти.Когда вы освобождаете закрепленный дескриптор, связанный объект будет откреплен и станет пригодным для сбора мусора, если на него нет других ссылок.

Так что, если неподкрепленный, или обычный GCHandle, был создан дляобъект управляемого класса с именем fooObj,

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

нужно ли его освобождать с помощью Free ()?

gch.Free();

Или GC освобождает его, когда он не требуется?

* 1016Причина, по которой я не хочу освобождать его, заключается в том, что в следующем коде мне нужно, чтобы paramsArgVPtr и gch1 продолжали ссылаться на объект fooObj даже после выделения и освобождения дополнительных GCHandles, таких как gch2.Но похоже, что после освобождения 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();
}
...