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