Reputation: 86124
A coworker of mine made the claim that delegates are always pinned in the heap in .net. I can't seem to find any authoritative source on whether this information is true.
Is it true?
Upvotes: 3
Views: 477
Reputation: 564611
The delegate itself is not pinned, and free to be moved by the GC. However, this does not necessarily mean you'd need to pin it.
At JIT time, the unmanaged code that is generated, and what is actually used if you're using an unmanaged function pointer to call the delegate's code, will not be moved. Chris Brumme (of the CLR team) explained this in detail on his blog (the key sentence here is This stub exists in fixed memory outside of the GC heap.):
Along the same lines, managed Delegates can be marshaled to unmanaged code, where they are exposed as unmanaged function pointers. Calls on those pointers will perform an unmanaged to managed transition; a change in calling convention; entry into the correct AppDomain; and any necessary argument marshaling. Clearly the unmanaged function pointer must refer to a fixed address. It would be a disaster if the GC were relocating that! This leads many applications to create a pinning handle for the delegate. This is completely unnecessary. The unmanaged function pointer actually refers to a native code stub that we dynamically generate to perform the transition & marshaling. This stub exists in fixed memory outside of the GC heap.
However, the application is responsible for somehow extending the lifetime of the delegate until no more calls will occur from unmanaged code. The lifetime of the native code stub is directly related to the lifetime of the delegate. Once the delegate is collected, subsequent calls via the unmanaged function pointer will crash or otherwise corrupt the process. In our recent release, we added a Customer Debug Probe which allows you to cleanly detect this – all too common – bug in your code. If you haven’t started using Customer Debug Probes during development, please take a look!
So your corworker is technically not correct - the delegate can be moved, and is not pinned. However, the coworker was "correct" in spirit - you do not necessarily need to pin the delegate if you're using an unmanaged function pointer to call it, though you do need to guarantee the delegate's lifetime.
Upvotes: 4
Reputation: 755091
This is simply not true. Delegates are not pinned in .Net.
Delegates act as if they are pinned when they are used as a parameter to a PInvoke function. The CLR allocates a native thunk which holds a reference to the delegate. But this reference does not pin the delegate nor does it act as a strong reference to the object.
Do note that pinning an object is not free. It actually incurs a fairly significant cost to the GC. It is fine in small doses but having every .Net delegate be pinned would likely have a very noticeable impact on performance
Upvotes: 4