Освобождение пространства динамической памяти
После того как мы рассмотрели как распределять пространство динамической памяти и выполнять инициализацию объектов, осталось рассмотреть как осуществляется освобождение более не используемого пространства динамической памяти.
Существует два способа освобождения пространства, которое было распределено в области динамической памяти, для его последующего повторного использования:
библиотека времени выполнения выполняет неявное освобождение распределеного пространства когда использованый для распределения пространства динамической памяти тип выходит из области видимости
Для этого случая примечательно то, что если тип описан на уровне библиотеки, то освобождение памяти не произойдет вплоть до завершения работы программы.
выполнение явного освобождения пространства динамической памяти в программе
Следует заметить, что стандарт языка Ада не определяет более четких требований и правил для алгоритмов библиотеки времени выполнения.
Поэтому, реальные алгоритмы будут определяться реализацией конкретного компилятора и его библиотек поддержки.
Следовательно, для уточнения этих сведений необходимо обратиться к документации на используемый компилятор, и здесь этот способ рассматриваться не будет.
Если вам необходимо освободить память (подобно тому как это делает системный вызов free в UNIX), то вы можете конкретизировать настраиваемую процедуру Ada.Unchecked_Deallocation.
Эта процедура называется непроверяемой (unchecked) поскольку компилятор не осуществляет проверку отсутствия ссылок на освобождаемый объект.
Таким образом, выполнение этой процедуры может привести к появлению "висячих" ссылок.
generic
type Object(<>) is limited private; type Name is access Object; procedure Ada.Unchecked_Deallocation(X : in out Name); pragma Convention(Intrinsic, Ada.Unchecked_Deallocatoin); |
Для показанного ранее ссылочного типа Element_Ptr, значения которого ссылаются на объекты типа Element
это может быть конкретизировано следующим образом:
procedure Free is new Ada.Unchecked_Deallocation(Object => Element, Name => Element_Ptr); |
Теперь, можно написать рекурсивную процедуру Free_List, которая будет удалять список, состоящий из объектов типа Element.
Начало списка будет указываться параметром процедуры Free_List, а для непосредственного удаления объекта типа Element
процедура Free_List будет использовать процедуру Free:
with Free; procedure Free_List (List_Head: in out Element) is begin if List_Head.Next /= null Free_List(List_Head.Next); -- рекурсивный вызов end if; Free(List_Head); end Free_List; |
начало которого указывается переменной Head_Element
можно выполнить следующее:
. . . Free_List(Head_Element); . . . |
При описании ссылочного типа Element_Ptr, может быть использована директива компилятора Controlled:
. . . type Element_Ptr is access Element; pragma Controlled(Element_Ptr); . . . |