показана ситуация, когда сначала
На рисунке 8. 6 показана ситуация, когда сначала были выделены пять блоков памяти, а затем второй и четвертый освобождены. Теперь, хотя доступны 1000 байтов, невозможно выделить больше 600 байтов, потому что память раздроблена на небольшие блоки. Даже когда третий блок освободится, памяти будет достаточно только при условии, что менеджер кучи «умеет» сливать смежные свободные блоки.
В добавление к слияниям менеджер кучи может предупреждать фрагментацию, отыскивая блок подходящего размера, а не просто первый доступный, или выделяя большие блоки из одной области динамической памяти, а небольшие блоки — из другой. Существует очевидный компромисс между сложностью менеджера и издержками времени выполнения.
Программист должен знать используемые алгоритмы управления динамической памятью и писать программу с учетом этих знаний.
Другая возможность ослабить зависимость от алгоритмов работы менеджера кучи — это завести кэш освобождаемых блоков. Когда блок освобождается, он просто подсоединяется к кэшу. Когда необходимо выделить блок, сначала проверяется кэш; это позволяет избежать издержек и фрагментации, возникающих при обращениях к менеджеру кучи.
В Ada есть средство, которое позволяет программисту задать несколько куч разного размера, по одной для каждого типа указателя. Это позволяет предотвратить фрагментацию, но повышает вероятность того, что в одной куче память будет исчерпана, в то время как в других останется много свободных блоков.
Виртуальная память
Есть один случай, когда распределение динамической памяти совершенно надежно — это когда используется виртуальная память. В системе с виртуальной памятью программисту предоставляется настолько большое адресное пространство, что переполнение памяти фактически невозможно. Операционная система берет на себя распределение логического адресного пространства в физической памяти, когда в этом возникает необходимость.