Осколок памяти - это та же концепция, что и фрагментация диска: это означает, что пространство теряется, потому что используемые области недостаточно плотно собраны вместе.
Пусть для простого примера игрушки, что у вас есть десять байт памяти:
| | | | | | | | | | |
0 1 2 3 4 5 6 7 8 9
Теперь давайте выделить три три байта блока, имя A, B, и C:
| A | A | A | B | B | B | C | C | C | |
0 1 2 3 4 5 6 7 8 9
сейчас освободить блок B:
| A | A | A | | | | C | C | C | |
0 1 2 3 4 5 6 7 8 9
Что произойдет, если мы попытаемся выделить четырехбайтовый блок D? Ну, у нас есть четыре байта свободной памяти, но у нас нет четырех смежных байтов свободной памяти, поэтому мы не можем выделить D! Это неэффективное использование памяти, потому что мы должны были бы хранить D, но мы не смогли. И мы не можем перемещать C, чтобы освободить место, потому что очень вероятно, что некоторые переменные в нашей программе указывают на C, и мы не можем автоматически находить и изменять все эти значения.
Как вы знаете, что это проблема? Наилучшим образом, самый большой знак - размер вашей виртуальной памяти вашей программы значительно больше, чем объем используемой вами памяти. В реальном мире у вас будет много более десяти байтов памяти, поэтому D просто получит выделение, начиная с байта 9, а байты 3-5 останутся неиспользованными, если вы позже не выделили что-то три байта или меньше.
В этом примере 3 байта не так много, чтобы отбросить их, но рассмотрим более патологический случай, когда два выделения из пары байтов, например, разделяются на десять мегабайт в памяти, и вам нужно выделить блок размером 10 мегабайт + 1 байт. Вы должны попросить ОС более десяти мегабайт больше виртуальной памяти, чтобы сделать это, даже если вы просто один байт, застенчивый, имея достаточно места.
Как вы его предотвращаете? Наихудшие случаи имеют тенденцию возникать, когда вы часто создаете и уничтожаете маленькие объекты, поскольку это имеет тенденцию производить эффект «швейцарского сыра» со многими маленькими предметами, разделенными множеством маленьких отверстий, что делает невозможным выделение больших объектов в этих отверстиях. Когда вы знаете, что собираетесь это делать, эффективная стратегия состоит в том, чтобы предварительно выделить большой блок памяти в качестве пула для ваших маленьких объектов, а затем вручную управлять созданием небольших объектов внутри этого блока, а не позволять по умолчанию используется распределитель по умолчанию.
В общем, чем меньше выделений вы используете, тем менее вероятно, что память будет фрагментирована. Однако STL справляется с этим довольно эффективно. Если у вас есть строка, которая использует всю ее текущее распределение, и вы добавляете к ней один символ, она не просто перераспределяет ее текущую длину плюс одну, то удваивает свою длину. Это вариация стратегии «пул для частых небольших распределений». Строка захватывает большой кусок памяти, чтобы он мог эффективно справляться с повторным небольшим увеличением размера без повторных небольших перераспределений. Все контейнеры STL на самом деле делают такие вещи, поэтому обычно вам не нужно слишком беспокоиться о фрагментации, вызванной автоматически перераспределяющимися контейнерами STL.
Хотя, конечно, контейнеры STL не объединяют память между, поэтому, если вы собираетесь создавать множество небольших контейнеров (а не несколько контейнеров, которые часто меняются), вам может потребоваться предотвратить фрагментации так же, как и для любых часто создаваемых небольших объектов, STL или нет.
Много больших ответов, спасибо всем! – AshleysBrain
Есть уже много отличных ответов, но вот несколько фотографий из реального приложения (Firefox), где фрагментация памяти была большой проблемой: http://blog.pavlov.net/2007/11/10/memory-fragmentation/ –
@ MariusGedminas ссылка больше не работает, поэтому важно предоставить краткое резюме вместе со ссылкой или ответить на вопрос с резюме со ссылкой – katta