Опубликован: 17.10.2005 | Уровень: специалист | Доступ: платный
Лекция 9:

Управление памятью

Аннотация: Честно говоря, было бы неплохо забыть про память. Программы создавали бы объекты по мере надобности. Неиспользованные объекты исчезали бы в небытие, а необходимые медленно передвигались бы вверх. Этот процесс подобен движению по служебной лестнице работника большой корпорации, в конце карьеры достигшего уровня руководства. Но это не так. Память не безгранична и не организуется в непрерывный ряд слоев с уменьшающейся скоростью доступа. Нам необходимо увольнять наших бестолковых работников даже, если мы должны называть это ранним уходом на пенсию, продиктованным общей экономической ситуацией. Эта лекция изучает, кто все же должен быть сокращен, кем и как.

Что происходит с объектами

ОО-программа создает объекты. Предыдущая лекция показала, как полезно полагаться на динамическое создание для получения гибких объектных структур, подстраивающихся автоматически к нуждам системы.

Создание объектов

Мы рассмотрели базовые операции размещения новых объектов. Простейший способ размещения записывается как

create x

и его эффект был определен триадой: создать новый объект; связать его со ссылкой x ; и инициализировать его поля.

Вариант этой инструкции вызывает процедуру инициализации; можно также создать новый объект с помощью подпрограмм clone и deep_clone. Так как все эти формы размещения основаны на одной и той же базисной инструкции создания, можно без потери общности ограничиться рассмотрением create x .

Рассмотрим эффект, создаваемый инструкциями управления памятью.

Три режима управления объектами

Во-первых, будет полезным расширить рамки дискуссии. Форма управления объектами, используемая для ОО-вычислений, может поддерживаться одним из трех обычно встречаемых режимов: статическим, стековым и динамически распределяемым. Выбор режима определяет, как сущности присоединяются к объектам.

Напомним, что сущность - это имя в тексте программы, представляющее некоторое значение или совокупность значений в период выполнения. Такие значения являются либо объектами, либо (возможно неопределенными) ссылками на объект. Сущностями являются атрибуты, формальные аргументы подпрограмм, локальные переменные подпрограмм и Result. Термин присоединение описывает связь между сущностью и объектом: на определенном этапе выполнения программы сущность x присоединяется к объекту О, если значение x есть либо О (для x развернутого типа), либо ссылка на О (для x ссылочного типа). Если x присоединен к О, часто говорят также, что О присоединен к x. Ссылка может быть присоединена не более чем к одному объекту, объект может быть присоединен к двум и более ссылкам. Проблема динамических псевдонимов обсуждалась в предыдущей лекции.

В статическом режиме сущность может быть присоединена максимум к одному объекту в процессе выполнения программы. Эта схема, поддерживаемая в таких языках как Fortran, резервирует место для всех объектов и присоединяет объект к имени раз и навсегда при загрузке программы или в начале ее выполнения.

Статический режим

Рис. 9.1. Статический режим

Статический режим прост и эффективно реализуем архитектурой обычного компьютера. Но он имеет серьезные ограничения:

  • Препятствует рекурсии. Рекурсивной программе необходимо иметь несколько одновременно активных копий, каждой со своими экземплярами сущностей.
  • Препятствует созданию динамических структур данных. Компилятор должен уметь определять точный размер каждой структуры данных из текста программы. Каждый массив, например, должен в этом случае объявляться статично со своим строгим размером. Это серьезно ограничивает мощность языка: становится невозможным оперировать структурами, растущими в ответ на события выполнения. Приходится резервировать максимально возможную память для каждой из структур - это не только неэффективно, но и довольно опасно. Если размер одной из структур данных недооценен, это, скорее всего, вызовет ошибку выполнения системы.

Второй режим размещения объектов - режим стека. Здесь сущность может быть в реальном времени последовательно присоединяться к нескольким объектам. Механизм выполнения размещает и удаляет эти объекты в порядке "последним пришел, первым ушел". Когда объект удаляется, относящаяся к нему сущность присоединяется вновь к объекту, с которым она была связана до появления нового элемента, если, конечно, такой объект существует.

Режим, основанный на стеке

Рис. 9.2. Режим, основанный на стеке

Основанное на стеке управление объектами сделало популярным Algol 60 и с тех пор поддерживается (часто вместе с другими двумя режимами) в большинстве языков. Такой способ поддерживает рекурсию и динамические массивы, границы которых выясняются в процессе выполнения. В Pascal и C этот механизм не применяется к массивам, как это делается в Algol. Однако разработчикам хотелось бы чаще всего именно массивы распределять таким способом. Тем не менее, даже если этот механизм и может быть применен к массивам, размещение в стеке большинства сложных структур данных невозможно1Динамические массивы могут создаваться в языке С, используя функцию mallok - механизм, подобный денамическому распределению, описываемому ниже; некоторые расширения Pascal поддерживают динамические массивы.

Для сложных структур данных нам нужен третий и последний режим: динамическая память, называемая также "кучей", из-за способа ее использования. Это память, в которой объекты создаются динамически по запросу. Сущности могут динамически присоединяться к разным объектам. Во время компиляции обычно нельзя предсказать, какие объекты будут созданы и присоединены к сущности. Кроме того, объекты могут содержать ссылки на другие объекты.

Динамический режим

Рис. 9.3. Динамический режим

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

Использование динамического режима

Динамический режим, очевидно, наиболее общий, и он необходим для ОО-программирования. Его используют многие не ОО-языки. В частности:

  • Pascal использует статический режим для массивов, режим, основанный на стеке, для переменных, не являющихся массивами и указателями, динамический режим для указателей. В последнем случае создание объекта выполняется с помощью вызова специальной процедуры создания new.
  • Язык C похож на Pascal, но дополнительно вводит динамические массивы и статические переменные, не являющиеся массивами, Язык С динамически размещает переменные типа указатель и массивы, используя библиотечную функцию malloc.
  • PL/I поддерживает все модели.
  • Lisp системы традиционно были высоко динамичны и полагались большей частью на динамический режим распределения памяти. Одна из наиболее важных операций Lisp, используемая многократно для представления списков, - CONS, создает структуру из двух полей. В первом поле хранится значение элемента, а во втором - указатель на следующий элемент. Здесь CONS, скорее источник новых объектов, чем инструкция их создания.
Александр Шалухо
Александр Шалухо
Анатолий Садков
Анатолий Садков

При заказе pdf документа с сертификатом будет отправлен только сертификат или что-то ещё?

Алексей Щербанов
Алексей Щербанов
Россия, г. Оренбург
Ксения Маковецкая
Ксения Маковецкая
Россия, Москва, МГЮА им. О.Е. Кутафина, 2014