Stats

Contributors: 1 Thursday, August 4, 2016
Licensed under: CC-BY-SA
Not affiliated with Stack Overflow
Rip Tutorial: riptutorial@gmail.com
Roadmap: roadmap

Pinned Object

Download c# eBook

Example

GC (Garbage Collector) is responsible for cleaning our garbage.

While GC cleans our garbage, he removes the unused objects from the managed heap which cause heap fragmentation. When GC is done with the removal, it performs a heap compression (defragmintation) which involves moving objects on the heap.

Since GC isn't deterministic, when passing managed object reference/pointer to native code, GC can kick in at any time, if it occurs just after Inerop call, there is a very good possibility that object (which reference passed to native) will be moved on the managed heap - as a result, we get an invalid reference on managed side.

In this scenario, you should pin the object before passing it to native code.

Pinned Object

Pinned object is an object that is not allowed to move by GC.

Gc Pinned Handle

You can create a pin object using Gc.Alloc method

GCHandle handle = GCHandle.Alloc(yourObject, GCHandleType.Pinned); 
  • Obtaining a pinned GCHandle to managed object marks a specific object as one that cannot be moved by GC, until freeing the handle

Example:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern void EnterCriticalSection(IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern void LeaveCriticalSection(IntPtr ptr);
       
public void EnterCriticalSection(CRITICAL_SECTION section)
{
    try
    {
        GCHandle handle = GCHandle.Alloc(section, GCHandleType.Pinned); 
        EnterCriticalSection(handle.AddrOfPinnedObject());
        //Do Some Critical Work
        LeaveCriticalSection(handle.AddrOfPinnedObject());
    }
    finaly
    {
        handle.Free()
    }
}

Precautions

  • When pinning (especially large ones) object try to release the pinned GcHandle as fast as possible, since it interrupt heap defragmentation.
  • If you forget to free GcHandle nothing will. Do it in a safe code section (such as finaly)