Devo eliminare le strutture sottoposte a marshalling tramite Marshal.PtrToStructure in codice non gestito?

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

  •  20-08-2019
  •  | 
  •  

Domanda

Ho questo codice C ++:

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

    //do stuff to foo
}

Quindi in C # chiamo la funzione così:

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

Dove MyDataStructure è una struttura (non di classe) che corrisponde a MY_DATA_STRUCTURE e i membri vengono raggruppati in modo appropriato.

Quindi domande: devo archiviare pData e poi rilasciarlo nuovamente in codice non gestito quando MyDataStructure è GC? MSDN dice per Marshal.PtrToStructure (IntPtr, Type): " Marshals i dati da un blocco di memoria non gestito a un oggetto gestito appena allocato del tipo specificato. " In quella frase fa & Quot; Marshall & Quot; significa " copia " ;? Nel qual caso dovrei conservare (IntPtr pData) e poi passarlo a codice non gestito (nel distruttore MyDataStructure) in modo da poter fare un C ++ & Quot; delete & Quot ;?

Ho cercato ma non riesco a trovare una risposta sufficientemente esplicita per questo.

È stato utile?

Soluzione

Come ha detto Erik, il Maresciallo significa copia, ma non credo che abbia risposto al punto principale della tua domanda.

È necessario mantenere il puntatore nativo pData fino a quando MyDataStructure è GCed? No.

Una volta eseguito il marshalling, l'istanza MyDataStructure, foo, contiene una copia della struttura a cui punta pData. Non è più necessario conservare pData. Per evitare una perdita di memoria, è necessario passare quel pData in un'altra funzione non gestita che lo eliminerà e che può essere eseguita subito dopo il marshalling, indipendentemente dal tempo in cui si tiene l'istanza MyDataStructure.

Altri suggerimenti

Sì, in questo caso Marshall significa copia; pertanto, è necessario deallocare la memoria in codice non gestito. Tutta la chiamata a PtrToStructure fa leggere un numero di byte indicato dalla dimensione della struttura di destinazione "MyDataStructure" dalla posizione di memoria indicata da pData.

I dettagli ovviamente dipendono esattamente dall'aspetto di "MyDataStructure" (usi gli attributi FieldOffset o StructLayout in MyDataStructure) - ma il risultato finale è che il ritorno da PtrToStructure è una copia dei dati.

Come GBegen sottolinea in la sua risposta , non ho risposto al punto principale della tua domanda. Sì, dovrai eliminare la copia non gestita della tua struttura in codice non gestito, ma no, non è necessario conservare su pData: puoi eliminare la copia non gestita non appena termina la chiamata a PtrToStructure.

PS: ho modificato il mio post in modo da contenere queste informazioni in modo da consolidare le risposte in un post: se qualcuno vota questa risposta, si prega di valutare anche la risposta di GBegen per il suo contributo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top