Нужно ли мне удалять структуры, маршалированные с помощью Marshal.PtrToStructure в неуправляемом коде?

StackOverflow https://stackoverflow.com/questions/497133

  •  20-08-2019
  •  | 
  •  

Вопрос

У меня есть этот код на C ++:

extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo)
{
    *foo = new MY_DATA_STRUCTURE;

    //do stuff to foo
}

Затем в C # я вызываю функцию таким образом:

[DllImport("MyDll.dll")]
static extern void AllocateFoo(out IntPtr pMyDataStruct);

...

MyDataStructure GetMyDataStructure()
{
    IntPtr pData;
    ManagedAllocateFooDelegate(out pData);

    MyDataStructure foo = (MyDataStructure)Marshal.PtrToStructure(pData, typeof(MyDataStructure));
    return foo;
}

Где MyDataStructure - это структура (не класс), которая соответствует MY_DATA_STRUCTURE, а члены упорядочены соответствующим образом.

Итак, вопросы:нужно ли мне сохранять pData, а затем снова выпускать его в неуправляемом коде, когда MyDataStructure является GC'd?В MSDN указано для Marshal.PtrToStructure(IntPtr, тип):"Маршалирует данные из неуправляемого блока памяти во вновь выделенный управляемый объект указанного типа". В этом предложении "маршалировать" означает "копировать"?В каком случае мне нужно было бы сохранить (IntPtr pData), а затем передать его в неуправляемый код (в деструкторе MyDataStructure), чтобы я мог выполнить "удаление" C ++?

Я искал, но не могу найти достаточно четкого ответа на этот вопрос.

Это было полезно?

Решение

Как сказал Эрик, Маршал действительно имеет в виду копию, но я не думаю, что он ответил на главный вопрос вашего вопроса.

Нужно ли вам удерживать собственный указатель pData до тех пор, пока MyDataStructure не будет GCed?Нет.

После маршалирования ваш экземпляр MyDataStructure, foo, содержит копию структуры, на которую указывает pData.Вам больше не нужно хранить pData.Чтобы избежать утечки памяти, вы должны передать эти pData в другую неуправляемую функцию, которая удалит их, и это можно сделать сразу после маршалинга, независимо от того, как долго вы удерживаете экземпляр MyDataStructure.

Другие советы

Да, в данном случае Маршалл означает копировать;таким образом, вам необходимо освободить свою память в неуправляемом коде.Все, что делает вызов PtrToStructure, - это считывает количество байтов, указанное размером целевой структуры 'MyDataStructure', из ячейки памяти, на которую указывает pData.

Детали, конечно, зависят от того, как именно выглядит 'MyDataStructure' (используете ли вы какие-либо атрибуты FieldOffset или StructLayout в MyDataStructure), но конечным результатом является то, что возврат из PtrToStructure является копией данных.

Как ГБеген указывает на то , что в его ответ, Я не ответил на главный вопрос вашего вопроса.Да, вам нужно будет удалить неуправляемую копию вашей структуры в неуправляемом коде, но нет, вам не нужно хранить pData - вы можете удалить неуправляемую копию, как только завершится вызов PtrToStructure.

PS:Я отредактировал свой пост, чтобы включить эту информацию, чтобы объединить ответы в один пост - если кто-нибудь поддержит этот ответ, пожалуйста, поддержите также ответ Гбегена за его вклад.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top