user1850479
user1850479

Reputation: 225

VirtualAlloc in c# to allocate large memory

I'm trying to adapt a vendor's c# example code for interfacing with a PCI-Express device. The code basically allocates a large buffer as an int array, and then pins it via the fixed keyword before handing it off to hardware to be filled with data.

This works great, but it eventually fails because .Net is limited to ~2 billion elements in an array. I can push the limit out to 16 GB by using an array of Long and gcAllowVeryLargeObjects keyword, but eventually I still run into .Net limitations.

In unmanaged code I could call VirtualAlloc and request 40 or 50GB directly, however its not clear to me if this is possible in c# and I haven't been able to find any good example code. I realize I could be doing this in a different language, but on Windows at least I'm more familiar with .Net, and aside from this relatively small portion of the program, there is very little hardware-specific code so I'd like to try and stick with what I have.

Upvotes: 2

Views: 8147

Answers (2)

Luaan
Luaan

Reputation: 63722

gcAllowVeryLargeObjects should work just fine, are you sure it doesn't? You may have to explicitly set the target CPU to x64 only.

In any case, you could use a hack struct to get a large value-type (which you can use as an array):

unsafe struct Test
{
  public fixed byte Data[1024];
}

unsafe void Main()
{
    Test[] test = new Test[16 * 1024 * 1024];

    // We've got 16 * 1024 * 1024 * 1024 here.
    fixed (Test* pTest = test)
    {

    }
}

This does have its limits (the unsafe structure has a maximum size), but it should get you where you need to be.

However, it might be better idea to simply call VirtualAlloc through P/Invoke. Or better, use Marshal.AllocHGlobal, it should really be doing the same thing (although you can't specify any parameters except for the size).

Upvotes: 1

jakobbotsch
jakobbotsch

Reputation: 6337

You can pinvoke VirtualAlloc. The signature is

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType lAllocationType, MemoryProtection flProtect);

You can find most pinvoke structures and signatures on pinvoke.net: VirtualAlloc

Alternatively, take a look at the AllocHGlobal func

Upvotes: 8

Related Questions