27

Suppose you're calling a Win32 function that will fill in your byte array. You create an array of size 32, empty. Then pass it in to the Win32 function to be filled int, and use it later in your managed code. Does there exist the chance that the byte array might be moved or overwritten in between the time it was allocated and it is filled in by the Win32 function?

Leeks and Leaks
  • 1,258
  • 1
  • 16
  • 26

3 Answers3

39

Short Answer: No, pinning is not necessary in this case

Longer Answer:

The CLR will automatically pin references to managed objects when they cross the PInvoke boundary. As soon as the PInvoke function exits the reference will be unpinned. So in situations like having a native function fill a byte[] no manually pinning is necessary because the object is only used by native code during the function call.

Manually pinning of the array becomes necessary if the native code caches the managed pointer. When this happens you must manually pin the array until the native code no longer needs the pointer. In this case I presume the pointer is not cached hence it's not necessary to pin

Reference - http://msdn.microsoft.com/en-us/magazine/cc163910.aspx#S2

TheBuzzSaw
  • 8,648
  • 5
  • 39
  • 58
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    Ok, so the question is what happens when the Win32 call doesn't return immediately? Say for example a call to ReadFile() that uses overlapped I/O and a manual reset event? The call returns immediately, while the I/O operation is performed. Does the byte array need to be pinned in that case? How is one to know whether the native library is caching the array – Leeks and Leaks Feb 08 '10 at 00:31
  • 1
    Well I should have read the link first because it gives ReadFileEx and overlapped I/O as an example of when you'd need to pin. – Leeks and Leaks Feb 08 '10 at 00:34
  • What do you mean by "the native code caches the managed pointer"? Does this mean that after the call to the native code (with providing the pointer), on following calls the previously provided pointer is used? (Link to reference is broken...) – royalTS Jun 19 '19 at 06:05
3

according to msdn Marshaling Arrays of Types only an array passed by reference can be written to by unmanaged code. So it appears that you must declare the array parameter [out] or [in,out] if you want to fill it in on the unmanaged side.

This page http://msdn.microsoft.com/en-us/library/aa719896(VS.71).aspx manages to go on and on without ever explicitly saying that the marshaller pins the arrays during the call from managed to unmanaged, but much of what it describes wouldn't work if the marshaller didn't pin.

John Knoeller
  • 33,512
  • 4
  • 61
  • 92
0

Sorry to answer my own question but I believe if the type is blittable, as byte[] is, then the array would be pinned while being marshalled by the runtime, so no pinning would be needed. An object on the other time would be different. Please correct me if I'm wrong.

Leeks and Leaks
  • 1,258
  • 1
  • 16
  • 26
  • 1
    What is the best way to pin a byte[] in C#? – Leeks and Leaks Feb 07 '10 at 21:41
  • 1
    You pin a byte[] by using the `fixed` keyword within an `unsafe` code block. See http://msdn.microsoft.com/en-us/library/f58wzh21(VS.71).aspx – Robert Harvey Feb 07 '10 at 21:46
  • 1
    @Reed: I think he's right here. The marshaller code will pin the array during the call from managaged to native, so the array would only need to be pinned explicitly if you wanted to reference it in the native code at some other time. – John Knoeller Feb 07 '10 at 21:53