Вы
при условии, что размер массива данных по крайней мере такой же большой. Это возможная ошибка в ожидании
Не проверяется результат malloc ()
В любом случае вам может не потребоваться делать это, просто передав указатель закрепленного байта хорошо (если вызываемая функция fx () каким-либо образом не изменяет данные, в этом случае, возможно, копия является требованием). Исходя из того, что память освобождается позже, вполне вероятно, что это невозможно.
Имея это в виду, здесь исправлена версия
void managed_fx (byte data __gc[], size_t size)
{
if (data.Length < size)
throw gcnew System.IndexOutOfRangeException(
"the unmanaged buffer is not big enough");
// Pin the data
byte __pin *pinned_data = &data [0];
// Copy data to the unmanaged buffer.
void *unmanaged_data = malloc (size);
if (unmanaged_data == NULL)
throw gcnew OutOfMemoryException(
"could not allocate memory for the unmanaged buffer");
memcpy (unmanaged_data, (byte*) pinned_data, size);
// Forward the call
fx (unamanged_data, size);
}
Чтобы ответить на дополнительные вопросы:
Закрепление необходимо сделать memcpy. Он не предотвращает удаление памяти во время выполнения GC (ну, технически это делает, но делает просто удержание ссылки на него), он предотвращает ее перемещение в памяти. Поскольку memcpy - неуправляемая функция - она не может обрабатывать указатели, которыми она манипулирует, перемещаясь в памяти.
malloc полностью неуправляемый (хотя библиотеки времени выполнения могут свободно использовать зарезервированные области управляемой кучи для этого).
В исходном C ++ / CLI нет четкого различия относительно того, является ли «код» управляемым или неуправляемым. При компиляции некоторые части будут представлять собой промежуточный код CIL, другие - простой нативный код. Важно то, являются ли используемые переменные управляемыми или неуправляемыми. Управляемой ссылкой (что-либо с ^) можно манипулировать / использовать только тот код, который сам управляется. Это означает, что среда выполнения может свободно изменять значения используемых указателей по своему усмотрению, если она изменяет расположение управляемого объекта в памяти. Это делает это способом, безопасным для управляемых функций (они останавливаются, пока мир вокруг них меняется).
Поскольку существует множество полезных функций, которые не знают, как обрабатывать такие управляемые ссылки, вам может понадобиться простой указатель на них.
Так как эта операция небезопасна (если GC запускает указатель перемещения), существует указатель закрепления, чтобы сделать его безопасным и простым, поскольку он одновременно принимает указатель и в течение срока службы этого указателя предотвращает перемещение во время выполнения указателя на переменную .