Last Updated:

pin  - managed object in C# [Pointer]

The keyword _pin indicates that the pointer to the managed object will remain correct (that is, the common language runtime (CLR will not move the object in memory) for the lifetime of the pinned pointer. A pinned Object remains in its place in memory as long as it is pointed to by a pinned pointer. If you change the pointer to point to another object or set it to zero, the object can be moved by the garbage collector. When the _pin (pin) keyword is not specified when defining a pointer, the common language runtime (CLR) can move the object that the pointer points to at any time.

Objects are moved due to garbage collection and compaction of dynamically allocated memory space performed by the common language runtime (CLR). These moves do not affect managed code because the common language runtime (CLR) automatically changes the values of managed pointers when objects are moved, but they can affect the execution of unmanaged code that uses unmanaged pointers to managed objects.

The keyword _pin (pin) should only be used when it is desperately needed, because pinning objects frustrates garbage collection and reduces its effectiveness. As an example of the need for pinning, mention a situation in which you pass a pointer to a managed object (or a pointer to a data element of such an object) as an argument to an unmanaged function. In this case, the problem is that during program execution, the managed object can be moved by the garbage collector, but the unmanaged function will use the old, incorrect pointer. This will cause the unmanaged function to turn to the wrong address and the consequences of this can be catastrophic.

The following is a snippet illustrating the use of the keyword _pin (pin) in the situation described. Note that the pPinnedObject object is fixed in memory, so passing a pointer to it to the SetGlobalPointerValue and GetGlobalPointerValue methods as an argument is valid. The implementation of these methods is based on the fact that the global pointer х remains correct, and this can only be true if the common language runtime (CLR) does not move the ManagedClass object. Note that the compiler is able to predict the occurrence of such a situation and will give an error message if you remove the keyword _pin (pin) from the above example.

//PinExample.cpp
#using <mscorlib.dll>
using namespace System;
// use namespace System;
_gc class ManagedClass
// garbage collector class ManagedClass
{
public:
intx; };
ttpragma unmanaged
int*gx; // global pointer void SetGlobalPointer(int* pi)
{
// set global pointer,
// to point to a managed object
gx = pi;
}
void SetGlobalPointerValue(int i)
{
// set managed entity item
// via global pointer
*gx = i;
}
int GetGlobalPointerValue()
{
// get the managed entity item
// via global pointer
return *gx;
}
Ipragma managed
void main()
{
ManagedClass _pin * pPinnedObject = new ManagedClass;
// note the error generated by the compiler
//in the next instruction...
// if the _pin keyword is removed from the previous instruction
SetGlobalPointer(&pPinnedObject › x); // unmanaged
SetGlobalPointerValue(1); // unmanaged
int x = GetGlobalPointerValue();//unmanaged
}