Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ГЭ-2013-анн-130515.doc
Скачиваний:
5
Добавлен:
01.05.2025
Размер:
1.69 Mб
Скачать

Простейшее распределение памяти

Рассмотрим простейшее распределение памяти, характерное для программы на «простом» языке, типа Фортрана, без запроса динамической памяти. В области памяти, предназначенной для программы, выделяется статический фрагмент для программы, данных и подпрограмм, а оставшаяся часть памяти используется как динамическая. Она используется для хранения локальных переменных подпрограмм, поэтому распределяется в виде стека, так как вызовы процедур и резервирование памяти для локальных переменных – это стековая работа. В каком порядке запросил, в таком (то есть, по сути, точно в обратном) и освободил. При распределении памяти в виде стека все хорошо, память распределяется плотно, алгоритм работает быстро.

Теперь рассмотрим эту же задачу для программы на Паскале. Статическая память выделяется так же точно, динамическая делится на две части: стек и кучу. Стек используется так, как в предыдущем случае, а куча применяется для хранения динамических переменных. В силу того, что программа запрашивает и освобождает память в произвольном порядке, нет гарантии, что первым освобождается последний запрошенный блок. При освобождении блока из середины занятого фрагмента памяти в нем образуется свободная область. Таким образом, при длительной работе программы в куче происходит накапливание дырок – пустот. Представьте отрезок, на одном конце находится стек, на другом – куча; они растут навстречу друг другу. Стек двигается туда-сюда, а куча только растет. Наконец, наступает момент, когда свободного места для выделения памяти нет, хотя в сумме памяти достаточно. Для ликвидации фрагментации можно, используя механизм сбора мусора, сжать кучу, тогда вся свободная память соберется в одном месте.

Выделение памяти блоками постоянной длины

Простейший метод распределения памяти, если невозможно использовать стековую дисциплину – выделять память фиксированными блоками. Пусть каждый блок имеет длину k, запрашиваемый элемент памяти – l, длина управляющей информации в блоке – b. Тогда количество выделяемых блоков памяти равно l/(k-b). В среднем на один запрашиваемый элемент за счет внутренней фрагментации теряется 0,5k памяти, поэтому задавать слишком большие блоки нецелесообразно. Слишком малые блоки тоже задавать нерационально: много места расходуется на управляющую информацию. Зная средний размер запрашиваемого элемента, легко вычислить оптимальный размер блока (сделайте это самостоятельно). Память выделяется, пока есть свободное пространство. Освобождаемые блоки помечаются, но в распределении не участвуют, то есть, куча растет как стек, но не убывает. Конечно, если освобождается элемент, запрошенный последним, он может объединиться с остальным свободным пространством. В этом случае дисциплина работы чисто стековая. Как только для очередного элемента станет недостаточно свободного пространства, запускается механизм сбора мусора.

Предложенный способ прост в реализации, но при интенсивных запросах памяти приводит к частым сборам мусора. Кроме того, нельзя не считаться с достаточно значительной внутренней фрагментацией.