Россия, Челябинск, Южно-Уральский Государственный Университет (НИУ) |
Управление памятью и сборка мусора
Пример стекового управления памятью памяти
Проиллюстрируем стековый механизм управления памятью с помощью небольшого примера на Паскале. На слайде приведена программа, использующая рекурсивную процедуру Digits для вычисления суммы цифр числа. При этом нам необходимо уметь различать экземпляры процедуры Digits , для этого необходимо создавать независимые активационные записи для различных экземпляров. На первом рисунке показан момент после первого рекурсивного вызова. После возврата в главную программу со стека снимаются не нужные более переменные и указатель вершины стека перемещается вниз (этот момент показан на втором рисунке).
Отметим, что в языках, в которых присутствует динамическая информация, в каждой рамке вначале распределяется вся статически известная память, а все остальные переменные размещаются над статической частью. Таким образом, в момент компиляции мы еще не знаем адреса рамок, но, по крайней мере, мы сможем распределять статические адреса относительно начала определенной рамки. Другой подход к решению проблемы размещения динамической информации связан с размещением в статической части только информации, известной во время компиляции, и указателей на сами переменные в динамическую часть рамки стека или в кучу.
Еще одно замечание связано с вопросом параллелизма: при наличии параллелизма невозможно гарантировать последовательность выходов из процедур и потому чисто стековый механизм управления памятью недостаточен (хотя эту проблему можно решить путем разветвления стека в момент распараллеливания процесса).
Управление кучей
Наконец, последним механизмом управления памятью является управление кучей . Этот механизм предназначен для работы со всеми структурами данных, которые по тем или иным причинам не пригодны для статического или стекового распределения памяти. Потребность в куче возникает всякий раз, когда выделение и освобождение памяти может потребоваться в непредсказуемый момент времени. Более того, большинство современных объектно-ориентированных языков программирования попросту не могут обойтись без динамического выделения и уничтожения объектов. Так что хорошо это или плохо, но управление кучей становится одним из основных механизмов управления памятью в современных системах.
При управлении кучей проблемы утилизации и уплотнения памяти становятся весьма серьезными: моменты возврата памяти не всегда очевидны, порядок возврата памяти просто непредсказуем, а память, отведенная для распределения под новые объекты, обычно напоминает решето. Решение этих проблем возлагается на механизм сборки мусора . В этом процессе выделенная ранее память пересматривается с целью обнаружения неиспользуемых фрагментов, а высвобожденная память передается для повторного использования. Сборка мусора впервые появилась в трансляторах с языка LISP, в котором концепция управления кучей была практически единственным механизмом управления памятью.
Наверное, самой критичной проблемой управления кучей является отслеживание активных элементов в памяти: как только возникнет потребность в освобождении дополнительной памяти, процесс сборки мусора должен будет утилизировать все неиспользуемые более фрагменты памяти. Определить, используется ли данный момент в программе, можно несколькими способами. Наиболее распространенными из них являются счетчики ссылок и различные алгоритмы разметки памяти.