This creates the ability to do a form of garbage collection in Ada as illustrated and annotated in the following code:
with Ada.Text_Io;
use Ada.Text_Io;
procedure Alloc is
type Info is record
I1 : Integer;
I2 : Integer;
end record;
type Info_Ptr is access Info;
-- The Storage_Size attribute would be useless here since:
-- 1) This access type will not go out of scope until program ends.
-- 2) There is no way to predict a Max_Objects_To_Allocate
procedure Do_Alloc is
Max_Objects_To_Allocate : constant := 2;
-- Maximum number of objects to be allocated before PInfo
-- PInfo (the local access type) will go out of scope.
-- It could be set to some large number if unknown, but
-- that could potentially use up a large chunk of memory.
type Pinfo is access Info;
-- This access type will go out of scope at end of Do_Alloc
-- procedure.
for Pinfo'Storage_Size use Info'Max_Size_In_Storage_Elements * Max_Objects_To_Allocate;
-- By setting the Storage_Size attribute of an access type
-- to the Size of the type * max number of objects to be allocated
-- it will be pointing to will cause the object pointed at to
-- become deallocated when the access type goes out of scope.
-- NOTE: If you try and allocate more then Max_Objects_To_Allocate,
-- you will receive a STORAGE_ERROR at run time.
MyInfo : Pinfo;
OtherInfo : Info_Ptr;
begin
MyInfo := new Info;
-- Allocate an Info object using the local access type (PInfo)
MyInfo := new Info;
-- Even though this will cause the last allocated object to be
-- inaccessable, the last object will still be deallocated when
-- the local access type goes out of scope.
OtherInfo := new Info;
-- Allocate an Info object using the non-local access type (Info_Ptr)
-- Doesn't go out of scope
-- The allocated Info objects pointed to by the local access type
-- are deallocated here, but not those of the non-local access type.
-- As a result, each iteration of this procedure produces a memory
-- leak from otherInfo, while both Infos allocated to MyInfo are
-- properly deallocated and therefor no leak.
end Do_Alloc;
begin
Put("Garbage Collection Test"); New_Line;
loop
Do_Alloc;
end loop;
end;