「大容量」(32バイト)の空きメモリがあるとします。
----------------------------------
| |
----------------------------------
次に、その一部を割り当てます(5つの割り当て)。
----------------------------------
|aaaabbccccccddeeee |
----------------------------------
ここで、最初の4つの割り当てを解放しますが、5番目の割り当ては解放しません。
----------------------------------
| eeee |
----------------------------------
次に、16バイトを割り当ててみます。ああ、それはできません。でも、空き容量は2倍近くあります。
仮想メモリを備えたシステムでは、物理アドレス空間ではなく仮想アドレス空間で連続して大規模な割り当てを行うだけでよいので、断片化は想像以上に問題ではありません。したがって、私の例では、ページサイズが2バイトの仮想メモリがある場合、16バイトの割り当てを問題なく行うことができます。物理メモリは次のようになります。
----------------------------------
|ffffffffffffffeeeeff |
----------------------------------
一方、仮想メモリ(はるかに大きい)は次のようになります。
------------------------------------------------------...
| eeeeffffffffffffffff
------------------------------------------------------...
メモリの断片化の典型的な症状は、十分なメモリが解放されているように見えても、大きなブロックを割り当てようとしてもできないことです。別の考えられる結果は、プロセスがメモリをOSに解放できないことです(OSから割り当てたすべてのブロックでまだ使用中のオブジェクトがあるため、これらのブロックは現在ほとんど使用されていません)。
C ++でのメモリの断片化を防ぐための戦術は、サイズや期待される寿命に応じて、さまざまな領域からオブジェクトを割り当てることによって機能します。したがって、多くのオブジェクトを作成して後ですべて一緒に破棄する場合は、それらをメモリプールから割り当てます。それらの間で行う他の割り当てはプールからのものではないため、メモリ内のそれらの間には配置されないため、結果としてメモリは断片化されません。
プログラムが長時間実行されていて、多くの割り当てと解放を行わない限り、通常はそれほど心配する必要はありません。リスクが最も高いのは、存続期間の短いオブジェクトと存続期間の長いオブジェクトが混在している場合ですが、それでもmalloc
役立つように最善を尽くします。基本的に、プログラムに割り当てエラーが発生するか、予期せずシステムのメモリ不足が発生するまで、これを無視します(テストでこれをキャッチしてください!)。
標準ライブラリは、メモリを割り当てる他の何よりも悪くはありません。標準コンテナにはすべてAlloc
、絶対に必要な場合に割り当て戦略を微調整するために使用できるテンプレートパラメータがあります。