kaalus kaalus - 5 months ago 58
C# Question

Does GCHandle.Alloc allocate memory?

I am using .NET Memory Profiler from SciTech to reduce memory allocations rate of my program and cut frequency of garbage collections.

Surprisingly, according to the profiler, the largest amount of allocations seems to be coming from GCHandle.Alloc calls I am doing to marshall existing .NET arrays to native OpenGL.

My understanding is that calling GCHandle.Alloc does not allocate memory, it only pins existing memory on the managed heap?

Am I wrong or is the profiler wrong?


.NET reference source is available for anyone to see, and you can have a look and find out for yourself.

If you dig into GCHandle.Alloc, you'll see the it calls a native method called InternalAlloc:

[System.Security.SecurityCritical]  // auto-generated
internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);

Drilling down into the CLR code, you see the internal call to MarshalNative::InternalAlloc, which ends up calling:

hnd = GetAppDomain()->CreateTypedHandle(objRef, type);

Which in turns calls ObjectHandle::CreateTypedHandle -> HandleTable::HndCreateHandle -> HandleTableCache->TableAllocSingleHandleFromCache which allocates the handle if the it doesn't exist in the cache.

As @Antosha corrected me, the place of invocation isn't via ComDelegate (which actually makes little since) but via MarshalNative. An allocation does occur, not on the managed heap, but an external heap reserved by the runtime for managing handle roots into GC objects. The only allocation that does occur in the managed heap is the IntPtr which holds to pointer to the address in the table. Despite this, you should still make sure to call GCHandle.Free once you're done.