アンマネージ コードで Marshal.PtrToStructure によってマーシャリングされた構造を削除する必要がありますか?
-
20-08-2019 - |
質問
この C++ コードがあります。
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 されたときにアンマネージ コードで再度解放する必要がありますか?MSDN では、Marshal.PtrToStructure(IntPtr, Type) について次のように述べています。「管理されていないメモリのブロックから、指定されたタイプの新しく割り当てられた管理されたオブジェクトへのマーシャルデータ。」その文では、「マーシャル」は「コピー」を意味しますか?この場合、(IntPtr pData) を保持してから、それをアンマネージ コード (MyDataStructure デストラクター内) に渡して、C++ の「削除」を行う必要があるでしょうか?
検索しましたが、これに対する十分に明確な答えが見つかりません。
解決
、元帥はコピーを意味しているのが、私は彼があなたの質問の主なポイントに答えないと思います。
あなたはMyDataStructureがGCedなるまでpDataをネイティブポインタ上に保持する必要がありますか?ノーます。
一度マーシャリングは、あなたのMyDataStructureインスタンスは、fooが、構造体のコピーがpDataをによって指さ含まれています。あなたはもはやpDataを上に保持する必要はありません。メモリリークを避けるために、あなたはそれを削除します別のアンマネージ関数にそのpDataをを渡す必要があり、それは関係なく、あなたがMyDataStructureインスタンスを保持どのくらいの、右のマーシャリング後に行うことができます。
他のヒント
はい、この場合、Marshall はコピーを意味します。したがって、アンマネージ コードでメモリの割り当てを解除する必要があります。PtrToStructure への呼び出しは、pData が指すメモリ位置から宛先構造体 'MyDataStructure' のサイズで示されるバイト数を読み取ることだけを行います。
もちろん、詳細は 'MyDataStructure' がどのようなものであるか (MyDataStructure で FieldOffset 属性または StructLayout 属性を使用するか) によって異なりますが、最終結果は PtrToStructure からの戻り値がデータのコピーになります。
として Gビーゲン で指摘する 彼の答え, 質問の主旨に答えていません。はい、アンマネージ コードで構造体のアンマネージ コピーを削除する必要がありますが、いいえ、pData を保持する必要はありません。PtrToStructure への呼び出しが完了したらすぐにアンマネージ コピーを削除できます。
追伸:回答を 1 つの投稿に統合するために、この情報を含むように投稿を編集しました。誰かがこの回答に賛成票を投じた場合は、彼の貢献に対して GBegen の回答にも賛成票を投じてください。