25

I'm writting a program in c# that uses a C++ library, and for some reason I need to allocate an unmanaged buffer to pass it to the lib. Is there a way to do this in c# ? Basically I would just need to do a malloc in C#...

Thanks

Blitzz
  • 735
  • 2
  • 7
  • 7
  • 2
    @John Saunders: I don't know if that would be reliable since the managed memory isn't guaranteed to be contiguous. You would probably want to pin it down too to prevent the GC from moving it while it was being used. – Joshua Apr 15 '10 at 20:11
  • 6
    @Joshua Huh? Managed memory is very much guaranteed to be contiguous. It's not guaranteed to stay in the same place, but when it does, it's contiguous, and there's `fixed` to keep it steady. – Roman Starkov Jan 04 '12 at 00:44
  • On another note, if you're passing the buffer into a function and the C++ program is done with it when it returns, you can use pinvoke, pass in a byte[] and let the compiler handle the rest for you. – Warty Jul 17 '16 at 02:56

4 Answers4

46

Try something like this:

using System;
using System.Runtime.InteropServices;

class Example
{
    static void Main()
    {
        IntPtr pointer = Marshal.AllocHGlobal(1024);
    }
}

This uses the Marshal.AllocHGlobal method:

Allocates memory from the unmanaged memory of the process by using the specified number of bytes.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • 27
    Make sure you free it with `FreeHGlobal()`. Also to be exception safe you probably want to make an `IDisposable` wrapper class to allocate the memory so that you can allocate in a `using` statement to free the memory on `Dispose`. – Ron Warholic Apr 15 '10 at 20:15
9

You can also use a byte array for this.

You do this by using an unsafe routine and the fixed statement:

static unsafe void PerformOperation()
{
    byte[] buf = new byte[1024];
    fixed (void* ptr = &buf[0])
    {
        SomeUnmanagedFunction(new IntPtr(ptr));
    }
}

The issue - and this is an important one - is that SomeUnmanagedFunction is not allowed to touch that pointer after it has returned and code has exited the fixed block. So if you do something like this:

static void PerformFabulousTrick()
{
    byte[] buf = new byte[1024];
    fixed (void *ptr = &buf[0])
    {
        SetBuffer(ptr, buf.Length);
    }
    FillBuffer(); // puts data in buf - NOT - may crash hard
}

you are asking for nothing but trouble. In this case you probably want to use a GCHandle, which can pin a managed object in the heap. This can also be troublesome in that you NEED to unpin it in a timely manner or you risk fragmenting your heap.

In general, I would recommend making sure that you're P/Invoking correctly into the function so that the maybe marshaller can do this work for you. I like fixed better than GlobalAlloc since its scope is clear. I can't decide which I like least of GlobalAlloc and GCHandle. Both require you to do more work since the GC or language won't do it for you.

plinth
  • 48,267
  • 11
  • 78
  • 120
3

This is how we need to assign and free unmanaged memory by using specific number of bytes.

// Demonstrate how to call GlobalAlloc and 
// GlobalFree using the Marshal class.
IntPtr hglobal = Marshal.AllocHGlobal(100);
Marshal.FreeHGlobal(hglobal)
Tunaki
  • 132,869
  • 46
  • 340
  • 423
0

Years later, in the meantime: In .net6, 7, MS gifted us with the class "NativeMemory" with methods like "AlignedAlloc", which might be useful for vectorized applications: MS writes for this example:

public static void* AlignedAlloc (UIntPtr byteCount, UIntPtr alignment);

"This method is a thin wrapper over the C aligned_alloc API or a platform dependent aligned allocation API such as _aligned_malloc on Win32."

Of course, no garbage collection in that case. One has to release the memory oneself to avoid memory leaks, by using "AlignedFree".

josh
  • 671
  • 5
  • 10