2009-01-30 2 views
11

У меня есть этот C++ код:Нужно ли удалять структуры, маршалированные через Marshal.PtrToStructure в неуправляемом коде?

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, Type): «Данные маршалов из неуправляемого блока памяти в новый выделенный управляемый объект указанного типа». В этом предложении «Маршалл» означает «копия»? В каком случае мне нужно будет сохранить (IntPtr pData), а затем передать его неуправляемому коду (в деструкторе MyDataStructure), чтобы я мог выполнить «удаление» на C++?

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

+0

Ваша неуправляемая функция AllocateFoo не работает так, как написано. Вам нужен дополнительный уровень косвенности, чтобы вернуть указатель обратно вызывающему. i.e., AllocateFoo (MY_DATA_STRUCTURE * * foo) { * foo = new MY_DATA_STRUCTURE; } – GBegen

+0

Да, вы правы! В моем фактическом коде используется PMY_DATA_STRUCTURE *, я отредактирую сообщение. – Serguei

ответ

10

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

Нужно ли удерживать указатель на pData, пока MyDataStructure не будет GCed? №

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

7

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

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

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

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

Смежные вопросы