¿Necesito eliminar estructuras ordenadas a través de Marshal.PtrToStructure en código no administrado?

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

  •  20-08-2019
  •  | 
  •  

Pregunta

Tengo este código C ++:

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

    //do stuff to foo
}

Luego en C # llamo 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;
}

Donde MyDataStructure es una estructura (no una clase) que corresponde a MY_DATA_STRUCTURE y los miembros se ordenan adecuadamente.

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

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

¿Fue útil?

Solución

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

¿Necesita mantener el puntero nativo pData hasta que MyDataStructure esté GCed? No.

Una vez ordenado, su instancia de MyDataStructure, foo, contiene una copia de la estructura señalada por pData. No necesita aferrarse a pData por más tiempo. Para evitar una pérdida de memoria, debe pasar esos pData a otra función no administrada que lo eliminará, y eso se puede hacer inmediatamente después de la clasificación, independientemente de cuánto tiempo se mantenga en la instancia de MyDataStructure.

Otros consejos

Sí, en este caso, Marshall significa copia; por lo tanto, debe desasignar su memoria en 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 señalada por pData.

Los detalles, por supuesto, dependen exactamente de cómo se ve '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 GBegen señala en su respuesta , no respondí el punto principal de su pregunta. Sí, deberá eliminar la copia no administrada de su estructura en el código no administrado, pero no, no necesita retener pData; puede eliminar la copia no administrada tan pronto como se complete la llamada a PtrToStructure.

PD: he editado mi publicación para que contenga esta información a fin de consolidar las respuestas en una publicación; si alguien vota a favor de esta respuesta, por favor, vote también la respuesta de GBegen por su contribución.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top