Dois-je supprimer des structures marshalées via Marshal.PtrToStructure dans du code non managé?

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

  •  20-08-2019
  •  | 
  •  

Question

J'ai ce code C ++:

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

    //do stuff to foo
}

Puis en C # j'appelle la fonction ainsi:

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

Où MyDataStructure est une structure (non une classe) qui correspond à MY_DATA_STRUCTURE et où les membres sont correctement organisés.

Donc, des questions: dois-je stocker pData, puis le relâcher à nouveau dans du code non géré lorsque MyDataStructure est GC'd? MSDN indique pour Marshal.PtrToStructure (IntPtr, Type): " Marshals les données d'un bloc de mémoire non géré vers un objet géré nouvellement alloué du type spécifié. " Dans cette phrase, & Quot; Marshall & Quot; signifie " copier " Dans ce cas, il faudrait conserver (IntPtr pData) puis le transmettre au code non managé (dans le destructeur MyDataStructure) pour pouvoir effectuer une opération C ++ & "Delete &";?

.

J'ai cherché mais je ne trouve pas de réponse suffisamment explicite à cet égard.

Était-ce utile?

La solution

Comme le disait Erik, le maréchal veut dire copie, mais je ne pense pas qu'il ait répondu à l'essentiel de votre question.

Devez-vous conserver le pointeur natif pData jusqu'à ce que MyDataStructure soit GCed? Non.

Une fois marshalé, votre instance MyDataStructure, foo, contient une copie de la structure pointée par pData. Vous n'avez plus besoin de conserver pData. Pour éviter une fuite de mémoire, vous devez transmettre ce pData à une autre fonction non gérée qui le supprimera. Cette opération peut être effectuée immédiatement après le marshaling, quelle que soit la durée pendant laquelle vous conservez l'instance MyDataStructure.

Autres conseils

Oui, dans ce cas, Marshall signifie copie; ainsi, vous devez libérer votre mémoire en code non géré. Pour appeler PtrToStructure, il faut lire un nombre d'octets indiqué par la taille de la structure de destination 'MyDataStructure' à partir de l'emplacement de la mémoire pointé par pData.

Les détails dépendent bien sûr de l'apparence exacte de "MyDataStructure" (utilisez-vous des attributs FieldOffset ou StructLayout dans MyDataStructure) - mais le résultat final est que le retour de PtrToStructure est une copie des données.

Comme indiqué par GBegen dans sa réponse , je n'ai pas répondu à l'essentiel de votre question. Oui, vous devez supprimer la copie non gérée de votre structure dans du code non managé, mais non, vous n'avez pas besoin de conserver pData. Vous pouvez supprimer la copie non managée dès que l'appel à PtrToStructure est terminé.

PS: J'ai modifié mon message pour qu'il contienne ces informations afin de regrouper les réponses dans un seul message. Si quelqu'un relit cette réponse, merci de bien vouloir également relayer la réponse de GBegen pour sa contribution.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top