выделение «неуправляемой» памяти в c # - PullRequest
21 голосов
/ 15 апреля 2010

Я пишу программу на c #, которая использует библиотеку C ++, и по какой-то причине мне нужно выделить неуправляемый буфер для передачи его в lib. Есть ли способ сделать это в C #? По сути, мне просто нужно сделать malloc в C # ...

Спасибо

Ответы [ 3 ]

39 голосов
/ 15 апреля 2010

Попробуйте что-то вроде этого:

using System;
using System.Runtime.InteropServices;

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

Используется метод Marshal.AllocHGlobal:

Выделяет память из неуправляемой памяти процесса, используя указанное количество байтов.

8 голосов
/ 16 апреля 2010

Вы также можете использовать байтовый массив для этого.

Это делается с помощью небезопасной процедуры и фиксированного оператора:

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

Проблема - и это важная проблема - в том, что SomeUnmanagedFunction не разрешается касаться этого указателя после того, как он вернулся и код вышел из фиксированного блока. Так что если вы делаете что-то вроде этого:

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
}

Вы просите только неприятностей. В этом случае вы, вероятно, захотите использовать GCHandle , который может закрепить управляемый объект в куче. Это также может быть проблематично, так как вам НУЖНО своевременно открепить его или вы рискуете фрагментировать свою кучу.

В общем, я бы порекомендовал убедиться, что вы правильно используете функцию P / Invoking, чтобы, возможно, маршаллер мог сделать эту работу за вас. Мне нравится исправление лучше, чем GlobalAlloc, поскольку его сфера применения ясна. Я не могу решить, что мне нравится меньше всего из GlobalAlloc и GCHandle. Обе требуют , чтобы вы выполняли больше работы, поскольку GC или язык не сделают этого за вас.

2 голосов
/ 18 января 2016

Это то, как нам нужно назначать и освобождать неуправляемую память, используя определенное количество байтов.

// Demonstrate how to call GlobalAlloc and 
// GlobalFree using the Marshal class.
IntPtr hglobal = Marshal.AllocHGlobal(100);
Marshal.FreeHGlobal(hglobal)
...