私の Windows/C++ アプリケーションは、オペレーターを使用してメモリ内に最大 1Gb のデータを割り当て、new
このデータを処理します。処理後、データは削除されます。
new
アプリケーションを終了せずに処理を再度実行すると、オペレーターへの 2 回目の呼び出しで ~1Gb のデータを割り当てることが失敗することに気付きました。
私は、Windows がメモリを返却することを期待しています。これは、他の Win32 呼び出しなどでより適切に管理できますか?
私の Windows/C++ アプリケーションは、オペレーターを使用してメモリ内に最大 1Gb のデータを割り当て、new
このデータを処理します。処理後、データは削除されます。
new
アプリケーションを終了せずに処理を再度実行すると、オペレーターへの 2 回目の呼び出しで ~1Gb のデータを割り当てることが失敗することに気付きました。
私は、Windows がメモリを返却することを期待しています。これは、他の Win32 呼び出しなどでより適切に管理できますか?
これは Windows の問題ではないと思います。delete または delete[] を正しく使用したかどうかを確認してください。おそらく、メモリを割り当て/解放しているコードを投稿すると役立つでしょう。
ほとんどのランタイム環境では、オペレーティング システムからアプリケーションに割り当てられたメモリはアプリケーション内に残り、オペレーティング システムに返されることはめったにありません。メモリ ブロックを解放すると、アプリケーション内からブロックを再利用できますが、オペレーティング システムに対して解放して他のアプリケーションで使用できるようにするわけではありません。
Microsoft の C ランタイム ライブラリは、_heapmin_region に _heap_free_region または _free_partial_region を呼び出して、VirtualFree を呼び出してオペレーティング システムにデータを解放させることにより、メモリをオペレーティング システムに戻そうとします。ただし、対応する領域のページ全体が空でない場合、それらは解放されません。これの一般的な原因は、C++ コンテナーのブックキーピング情報とストレージ キャッシュです。
これは、メモリの断片化 (実際にはアドレス空間の断片化) が原因である可能性があります。さまざまな要因が原因で、プログラムのアドレス空間に 1 GB の連続したホールが利用できなくなっています。実際には、メモリ管理のバグが疑われます (申し訳ありません) - リーク検出を使用してコードを実行しましたか?
非常に大きなメモリ ブロックを使用しているため、VirtualAlloc()とVirtualFree( )の使用を検討する必要があります。これらを使用すると、ヒープ マネージャーとやり取りするオーバーヘッド (メモリと時間) なしでページを直接割り当てて解放できるからです。
C++ を使用しているため、 placement newを使用して、この方法で割り当てたメモリ内に C++ オブジェクトを構築できることに注意してください。
この問題は、ほぼ確実にメモリの断片化です。32 ビット Windows では、割り当てることができる最大連続領域は約 1.1GB です (EXE 内のさまざまな DLL が、より大きな連続領域を使用できないため)。メモリ割り当て (または DLL ロード、またはメモリ マップされたファイル) の割り当てを解除した後、以前の 1GB 領域の途中で終了した場合、1GB を割り当てるための次の new の呼び出しに使用できる 1GB 領域がなくなります。したがって、失敗します。
VM Validatorを使用して、このプロセスを視覚化できます。