I am passing data from C#-Code to C++-Code and vice versa using P/Invoke. This works fine so far.
Lately I read a few articles (e.g. this one) about the need of pinning these data because the GC might rearrange or delete them while C++ is performing its tasks.
I consulted some Microsoft articles but for me they are not entirely clear concerning when pinning needs to be done manually. I understood this article in the way that the CLR assures that not problems can arise when the GC collects. It does that by either pinning data or copying them into unmanaged memory where the GC does not collect. So for me this means that the programmer does not need to take care of pinning. The example in this article doesn’t show any pinning either. I am still not sure though whether my conclusion is correct.
Digging further I found some more information for specific data types I use in my code:
long: Passed by value – must therefore not be pinned. But what about
IntPtr: I use AllocHGlobal() which allocates space in the unmanaged memory. The GC does not touch that. So no pinning is necessary.
byte: Passed by reference but pinned automatically. See here: As an optimization, arrays of blittable types and classes that contain only blittable members are pinned instead of copied during marshaling.
string: Passed by reference but pinned automatically. See here: Pinning is automatically performed during marshaling for objects such as String, however you can also manually pin memory using the GCHandle class.
'custom struct with strings': Here I am really not sure. Does the sentence "Pinning is automatically performed during marshaling for objects such as String […]" include string arrays and custom structs?
At the moment I don’t pin anything and the code works fine. Even when I force GC to collect while C++ is performing its tasks. But of course this doesn’t mean that it will always work fine.
I use .Net Framework 4.8.
Do I need to do pinning for the mentioned data types?
Source: Windows Questions C++