В Ada имеется настраиваемая процедура для освобождения объекта, на который больше нет ссылок. Эта процедура эквивалентна ``free'' в языке C или ``delete'' в C++. Эта настраиваемая процедура называется ``Unchecked_Deallocation''. Так как она настраиваемая, то при использовании ее необходимо конкретизировать необходимым ссылочным типом. По соглашению, конкретизированную процедуру обычно называют "Free".
А вот стандартное описание настраиваемой процедуры Unchecked_Deallocation:
generic type Object(<>) is limited private; type Name is access Object; procedure Unchecked_Deallocation(X : in out Name);
Обратите внимание, что при конкретизации необходимо передать ей два параметра: тип, и ссылочный тип для него. Ниже приведен простой пример, в котором создается процедура ``Free'', позволяющая освобождать неиспользуемые объекты:
procedure Free is new Unchecked_Deallocation(Tree_Node, Tree_Access);
После создания конкретизированной процедуры ``Free'', ее можно вызвать. Давайте продолжим наш пример; предположим, что элемент списка, созданный нами в одном из предыдущих разделов, больше не нужен. Нет проблем: нам достаточно просто вызвать созданную нами подпрограмму ``Free''.
Free(Current);
Когда Free возвратит управление, переменная Current будет иметь значение "null", а память, на которую ссылалось предыдущее значение Current, будет освобождена. При вызове любого экземпляра процедуры Unchecked_Deallocation, естественно, будут автоматически выполняться операции финализации освобождаемого объекта.
Здесь, как и в других языках, например, C, C++ или Pascal, возникает важная проблема: что делать, если другая переменная ссылается на тот же объект? В нашем примере ссылочная переменная ``Root'' продолжает ссылаться на объект, даже после того, как он перестает существовать. Любая попытка использования переменной Root для обращения к объекту может привести к непредсказуемым последствиям. Не смотря на то, что Ada обеспечивает определенную защиту при использовании ссылочных переменных, эта одна из тех проблем против которой в Ada (впрочем, как и в других языках) нет универсального средства защиты.
Это как раз та область, где стремление обеспечить безопасность вступает в противоречие со стремлением к достижению прогнозируемой эффективности. Некоторые языки программирования требуют, чтобы освобождение памяти выполнялось автоматически; это называется автоматической сборкой мусора. В качестве примеров можно привести Smalltalk, Eiffel, и Java. Это на самом деле очень удобно, так почему бы везде не использовать этот механизм? В действительности, автоматическая сборка мусора порождает ряд проблем:
Стандарт Ada не требует наличия автоматической сборки мусора, но при этом он достаточно четко определяет возможность реализации этого механизма. Производители компиляторов могут включать такую возможность по своему усмотрению. Стандарт Ada требует обязательного наличия процедуры Unchecked_Deallocation, которая просто ничего не делает, если присутствует автоматическая сборка. Если Вы используете Ada-компилятор без автоматической сборки мусора (а таких большинство) и Вас волнует вопрос некорректного освобождения памяти, изучите возможные варианты использования Unchecked_Deallocation.
Unchecked_Deallocation одинаково хорошо работает для всех объектов, включая массивы. Unchecked_Deallocation works just fine on any object, including arrays.
Какое из следующих утверждений истинно?
Перейти к предыдущему разделу | Перейти к следующему разделу | Вернуться к содержанию Урока 12 |
---|
David A. Wheeler (dwheeler@ida.org)
Исходная копия этого документа находится по адресу
"http://www.adahome.com/Tutorials/Lovelace/s12s6.htm".
Исходная копия перевода размещена на сайте http://www.ada-ru.org
Перевод: Юрий Королев
Общая редакция перевода: Г.Ю. Сисюк