メモリ割り当て方法の比較

適切な割り当て方法の選択

シナリオに適したメモリ割り当て API を選択するには、次のガイダンスを使用します。

シナリオ 推奨される API メモ
汎用 C++ の割り当て new / std::make_unique / std::make_shared C++ コードの既定の選択肢。 CRT ヒープを内部的に使用します。 RAII は自動クリーンアップを保証します。
汎用 C の割り当て malloc / calloc / realloc C コードの既定の選択肢。 プラットフォーム間で移植可能。
最大 1 MB を超える割り当て、またはページ レベルの制御が必要な割り当て VirtualAlloc ページの細分性 (通常は 4 KB) で割り当てます。 特定の保護属性 (PAGE_READWRITEPAGE_EXECUTE_READなど) を使用して、大きなアドレス範囲、保護ページ、またはメモリを予約するために使用します。
カスタム コントロールを使用した多数の小さな割り当て (プール アロケーターなど) HeapAlloc / HeapCreate 分離またはシリアル化制御用のプライベート ヒープを作成します。 HEAP_NO_SERIALIZEは、ヒープが排他的にシングル スレッドである場合にのみ使用します。
COM 相互運用機能 (マーシャリングされたメモリ) CoTaskMemAlloc メモリが COM アパートメントの境界を越えた場合に必要です。 MIDL で生成されたスタブでは、CoTaskMemAlloc/CoTaskMemFree が使用されます。
移動可能メモリを使用するレガシ コード GlobalAlloc / LocalAlloc 新しいコードでは避けてください。 これらは HeapAlloc に対するオーバーヘッドを増やし、主にクリップボード操作およびそれらを必要とする特定の Win32 API との下位互換性のために存在します。

Important

割り当てと割り当て解除の関数は常に正しくペアになります。 HeapAllocで割り当てられたメモリは、free()LocalFreeではなく、HeapFreeで解放する必要があります。 割り当て/割り当て解除ファミリを混在すると、ヒープの破損が原因で診断が困難になります。

Note

VirtualAlloc と HeapAlloc: VirtualAlloc は、ページの細分性で動作します (最小 4 KB、 SYSTEM_INFO.dwAllocationGranularityに合わせた予約、通常は 64 KB)。 VirtualAlloc を使用して多数の小さなオブジェクトを割り当てると、アドレス空間が無駄になります。 小さい頻繁な割り当てには HeapAlloc (または malloc/new) を使用します。 大きなアドレス領域を予約したり、ページ保護を制御したり、カスタム アロケーターを実装したりする必要がある場合は、VirtualAlloc を使用します。

詳細な比較

さまざまなメモリ割り当て方法の簡単な比較を次に示します。

GlobalAllocLocalAllocHeapAlloc の各関数は、最終的に同じヒープからメモリを割り当てますが、それぞれ少し異なる機能セットを提供します。 たとえば、メモリを割り当てられなかった場合は例外を発生するように HeapAlloc に指示できます。 LocalAlloc では使用できない機能です。 LocalAlloc ではハンドルの割り当てがサポートされており、ハンドル値を変更することなく、基になるメモリを再割り当てによって移動できます。 HeapAlloc では使用できません。

32 ビット Windows以降、GlobalAllocLocalAlloc は、プロセスの既定のヒープへのハンドルを使用して HeapAlloc を呼び出すラッパー関数として実装されます。 そのため、 GlobalAllocLocalAlloc のオーバーヘッドは HeapAlloc よりも大きくなります。

異なるヒープ アロケーターは、さまざまなメカニズムを使用して独特の機能を提供するため、正しい関数を使用してメモリを解放する必要があります。 たとえば、HeapAlloc で割り当てられたメモリは、LocalFreeGlobalFree ではなく HeapFree で解放する必要があります。 GlobalAlloc または LocalAlloc で割り当てられたメモリは、対応するグローバル関数またはローカル関数を使用してクエリ、検証、および解放する必要があります。

VirtualAlloc 関数を使用すると、メモリ割り当ての追加オプションを指定できます。 ただし、割り当てにはページの細分性が使用されるため、 VirtualAlloc を使用するとメモリ使用量が増加する可能性があります。

malloc 関数には、実行時に依存するという欠点があります。 新しい演算子には、コンパイラに依存し、言語に依存するという欠点があります。

CoTaskMemAlloc 関数には、C、C++、またはVisual Basicで適切に機能する利点があります。 MIDL では CoTaskMemAllocCoTaskMemFree を使用してメモリをマーシャリングするため、COM ベースのアプリケーションでメモリを共有する唯一の方法でもあります。

例示

グローバル関数とローカル関数

ヒープ関数

仮想メモリ関数