I want to pin an array of bytes which is 10 megabytes long so that managed and unmanaged code can work on it.

My scenario is that I have an unmanaged driver which reads some data from the device and writes it to the big array and the managed application just reads that data.

Something like this:

byte[] dataArray = new byte[10*1024*1024];

I want to pin dataArray so that GC does not move it.

What happens actually when I just run the application, I get a DataAbortApplication, and after reading on the internet I found out that I should pin the dataArray to avoid this error.

How/what should I do?

share|improve this question
1  
Check out the fixed statement msdn.microsoft.com/en-us/library/f58wzh21.aspx – Tawnos Apr 23 '14 at 20:45
    
Possible duplicate of stackoverflow.com/questions/13293133/… ? – LB2 Apr 23 '14 at 20:46
    
@FabianBigler: you mean I can't share the big array between managed and unmanaged code? – ShrShr Apr 23 '14 at 20:46
6  
This array can't move, it is too large so is allocated on the Large Object Heap. Whatever your problem might be is surely related to something else. Your "DataAbortApplication" is a meaningless diagnostic. – Hans Passant Apr 23 '14 at 20:53

There are 2 ways to do this. The first is to use the fixed statement:

unsafe void UsingFixed()
{
    var dataArray = new byte[10*1024*1024];
    fixed (byte* array = dataArray)
    {
        // array is pinned until the end of the 'fixed' block
    }
}

However, it sounds like you want the array pinned for a longer period of time. You can use GCHandles to accomplish this:

void UsingGCHandles()
{
    var dataArray = new byte[10*1024*1024];
    var handle = GCHandle.Alloc(dataArray, GCHandleType.Pinned);

    // retrieve a raw pointer to pass to the native code:
    IntPtr ptr = handle.ToIntPtr();

    // later, possibly in some other method:
    handle.Free();
}
share|improve this answer
4  
This will work if the managed and unmanaged code is in the same process. To share cross process you would need to use a memory mapped file. – Chris Hinton Apr 23 '14 at 20:48

Here is a class that can be used to pin a byte array until is disposed. However it sounds like a memory mapped file would be more appropriate in your scenario.

public class PinnedBuffer : IDisposable
{
    public GCHandle Handle { get; }
    public byte[] Data { get; private set; }

    public IntPtr Ptr
    {
        get
        {
            return Handle.AddrOfPinnedObject();
        }
    } 

    public PinnedBuffer(byte[] bytes)
    {
        Data = bytes;
        Handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            Handle.Free();
            Data = null;
        }
    }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.