Pinned Object
suggest changeGC (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)