2009-01-30 24 views
11

I tienen este código C++:¿Debo eliminar estructuras ordenadas mediante Marshal.PtrToStructure en código no administrado?

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

    //do stuff to foo 
} 

Luego, en C# I llamar a la función así:

[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; 
} 

Dónde MyDataStructure es una estructura (no clase) que corresponde a MY_DATA_STRUCTURE y los miembros se marshalled apropiadamente.

Preguntas: ¿necesito almacenar pData y luego liberarlo de nuevo en código no administrado cuando MyDataStructure es GC'd? MSDN dice para Marshal.PtrToStructure (IntPtr, Type): "Marshals datos de un bloque de memoria no administrado a un objeto gestionado recientemente asignado del tipo especificado." En esa oración ¿"Marshall" significa "copia"? ¿En ese caso necesitaría preservar (IntPtr pData) y luego pasarlo a un código no administrado (en el destructor MyDataStructure) para poder hacer una "eliminación" de C++?

He buscado pero no encuentro una respuesta suficientemente explícita para esto.

+0

Su función no administrada, AllocateFoo, no funciona como está escrita. Necesita un nivel adicional de indirección para devolver el puntero a la persona que llama. es decir, AllocateFoo (MY_DATA_STRUCTURE * * foo) { * foo = new MY_DATA_STRUCTURE; } – GBegen

+0

¡Sí, tienes razón! Mi código real usa PMY_DATA_STRUCTURE *, editaré la publicación. – Serguei

Respuesta

10

Como dijo Erik, el Marshal quiere decir copiar, pero no creo que haya respondido el punto principal de su pregunta.

¿Necesita mantener el puntero nativo pData hasta que MyDataStructure tenga GCed? Nº

Una vez calculada, la instancia MyDataStructure, foo, contiene una copia de la estructura apuntada por pData. No necesita retener pData por más tiempo. Para evitar una pérdida de memoria, debe pasar ese pData a otra función no administrada que lo eliminará, y eso puede hacerse inmediatamente después de la recopilación, independientemente de cuánto tiempo se aferre a la instancia de MyDataStructure.

7

Sí, en este caso, Marshall significa copia; por lo tanto, debe desasignar su memoria en un código no administrado. Todo lo que hace la llamada a PtrToStructure es leer una cantidad de bytes indicados por el tamaño de la estructura de destino 'MyDataStructure' desde la ubicación de memoria apuntada por pData.

Los detalles del curso dependen exactamente de cómo se vea 'MyDataStructure' (¿utiliza algún atributo FieldOffset o StructLayout en MyDataStructure)? Pero el resultado final es que el retorno de PtrToStructure es una copia de los datos.

Como señala en his answer, no respondí el punto principal de su pregunta. Sí, deberá eliminar la copia no administrada de su estructura en código no administrado, pero no, no necesita retener pData; puede eliminar la copia no administrada tan pronto como finalice la llamada a PtrToStructure.

PD: He editado mi publicación para que contenga esta información a fin de consolidar las respuestas en una sola publicación; si alguien ha votado esta respuesta, envíe por favor la respuesta de GBegen también por su contribución.

Cuestiones relacionadas