13

私はこの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++ の「削除」を実行できるようにする必要がありますか?

検索しましたが、これに対する十分に明確な答えを見つけることができません。

4

2 に答える 2

12

エリックが言ったように、元帥はコピーを意味しますが、彼があなたの質問の要点に答えたとは思いません。

MyDataStructure が GC されるまで、pData ネイティブ ポインターを保持する必要がありますか? いいえ。

マーシャリングされると、MyDataStructure インスタンス foo には、pData が指す構造のコピーが含まれます。もう pData を保持する必要はありません。メモリ リークを回避するには、その pData を削除する別のアンマネージ関数に渡す必要があります。これは、MyDataStructure インスタンスを保持している時間に関係なく、マーシャリングの直後に実行できます。

于 2009-01-30T21:19:00.203 に答える
8

はい、この場合、マーシャルはコピーを意味します。したがって、アンマネージ コードでメモリの割り当てを解除する必要があります。PtrToStructure へのすべての呼び出しは、pData が指すメモリ位置から宛先構造体 'MyDataStructure' のサイズによって示されるバイト数を読み取ることです。

もちろん、詳細は「MyDataStructure」がどのように見えるかによって異なります (MyDataStructure で FieldOffset または StructLayout 属性を使用しますか) - しかし、最終結果は、PtrToStructure からの戻り値はデータのコピーです。

GBegenが彼の答えで指摘しているように、私はあなたの質問の要点に答えませんでした。はい、アンマネージ コード内の構造体のアンマネージ コピーを削除する必要がありますが、いいえ、pData を保持する必要はありません。PtrToStructure の呼び出しが完了するとすぐに、アンマネージ コピーを削除できます。

PS:回答を1つの投稿に統合するために、この情報を含むように投稿を編集しました-誰かがこの回答に賛成票を投じた場合は、彼の貢献に対してGBegenの回答にも賛成票を投じてください

于 2009-01-30T20:53:00.177 に答える