5

のMSDNドキュメントからMarshal.AllocHGlobal

AllocHGlobal は、Marshal クラスの 2 つのメモリ割り当てメソッドの 1 つです。このメソッドは、Kernel32.dll から Win32 LocalAlloc 関数を公開します。

ローカルヒープではなくグローバルヒープにメモリを割り当てる GlobalAlloc API があることを考えると、このメソッドの名前は誤解を招きやすいのではないでしょうか?

AllocHGlobalではなく、名前を付ける理由はありましたAllocHLocalか?

更新: Simon はコメントで、Windows にはグローバル ヒープのようなものはもはや存在せず、APIGlobalAllocLocalAllocAPI は従来の目的のためだけに残っていると指摘しています。最近では、GlobalAllocAPI は のラッパーにすぎませんLocalAlloc

これは、API がまったく呼び出さGlobalAllocれない理由を説明していますが、API がAllocHGlobalグローバル ヒープを使用しない (できない) 場合に名前が付けられた理由も説明していませんGlobalAlloc。16 ビットのサポートが廃止された後の .NET 2.0 まで導入されなかったため、この名前付けはおそらく従来の理由によるものではありません。では、疑問が残ります。なぜMarshal.AllocHGlobal、誤解を招く名前が付けられているのでしょうか。

4

3 に答える 3

3

ドラッグ アンド ドロップまたはクリップボードを使用してアプリ間でデータ転送を行っているとします。STGMEDIUM構造体にデータを入力するには、 HGLOBAL. だからあなたは電話しますAllocHGlobal。したがって、名前。

この関数の主な用途は、HGLOBAL. が必要な場合は、 として使用できる値を生成したHGLOBALことを示すドキュメントを見つける必要があるため、他の名前で呼ばれると混乱します。AllocAnythingElseHGLOBAL

于 2012-10-09T10:02:32.490 に答える
2

これは、Windows バージョン 3 の昔にさかのぼります。当時は、「デフォルト ヒープ」という概念があり、GlobalAlloc() API 関数がそこから割り当てられていました。そのヒープから割り当てられたメモリは、すべてのプロセス間で共有できます。

32 ビット バージョンの Windows で変更され、プロセスはヒープを介してメモリを共有できなくなりました。これにより、「グローバル ヒープ」と「ローカル ヒープ」という用語が無意味になりました。デフォルトのヒープである「プロセス ヒープ」の概念がまだあります。GlobalAlloc() は、そのヒープから割り当てるようになりました。ただし、プロセスの境界を越えて共有することはできません。GlobalAlloc と Marshal.AllocHGlobal の実際の実装では、LocalAlloc() API 関数を使用します。もう 1 つの Windows 3 ホールドオーバー。最近の出来事にちなんで、より適切な名前が付けられています。次に、32 ビット Windows で GetProcessHeap() と共に HeapAlloc() を使用します。

使用するヒープについて合意することは、相互運用に関する重大な問題です。これは、ピンボークした不適切に記述された C コードで非常に頻繁に問題が発生します。呼び出し元が解放する必要がある割り当てられたメモリへのポインタを返すこのようなコードは、多くの場合、メモリ リークやアクセス違反のために失敗します。このような C コードは、malloc() 関数を使用して独自のヒープから割り当てます。これは、C ランタイム ライブラリによって作成されたプライベート ヒープです。そのようなメモリを解放する見込みはなく、どのヒープが使用されたかがわからず、CRT ヒープへのハンドルを取得する方法もありません。

これは、C コードがよく知られているヒープを使用する場合にのみ、うまくいく可能性があります。プロセスヒープのように。または、COM コードで使用される CoTaskMemAlloc()。マーシャル クラスのもう 1 人。pinvoke マーシャラーは、必要に応じて CoTaskMemFree() で常にメモリを解放することに注意してください。そのメモリが CoTaskMemAlloc() で割り当てられていない場合、それは Vista 以降ではカブームであり、XP ではサイレント リークです。

于 2012-10-08T11:21:26.120 に答える