I'm using an instance of package Ada.Containers.Formal_Indefinite_Vectors to store two kinds of polimorphic objects.
I have the following package where I instantiate the container:
with Interfaces.C;
with Root.Classes.Concrete_1;
with Root.Classes.Concrete_2;
package Root.Vectors is
type vector_t is tagged limited private;
subtype vectorIndex_t is Interfaces.C.int range 1 .. Interfaces.C.int'Last;
procedure pAppend (this : in out vector_t;
New_Item : Root.Classes.Parent_t'Class);
procedure pClear (this : in out vector_t);
private
--TODO: I have to define it correctly, it could be the problem
function "=" (Left, Right : Root.Classes.Parent_t'Class)
return Boolean is (True);
MaxSize : constant Natural := Natural'Max
(Root.Classes.Concrete_1.Concrete_1_t'Size,
Root.Classes.Concrete_2.Concrete_2_t'Size);
package polimorphicVector_pck is new
Ada.Containers.Formal_Indefinite_Vectors
(Index_Type => vectorIndex_t,
Element_Type => Root.Classes.Parent_t'Class,
"=" => "=",
Max_Size_In_Storage_Elements => MaxSize,
Bounded => True);
type vector_t is tagged limited
record
v : polimorphicVector_pck.Vector (Capacity => 1000); --TODO: magic number
end record;
end Root.Vectors;
package body Root.Vectors is
procedure pAppend (this : in out vector_t;
New_Item : Root.Classes.Parent_t'Class) is
begin
polimorphicVector_pck.Append (Container => this.v,
New_Item => New_Item);
end pAppend;
procedure pClear (this : in out vector_t) is
begin
polimorphicVector_pck.Clear (Container => this.v);
end pClear;
end Root.Vectors;
Then I test it with the following main:
with Root.Classes.Concrete_1;
with Root.Vectors;
procedure Main is
aVector : Root.Vectors.Vector_t;
begin
for idx in Natural range 1 .. 1000 loop
declare
--Concrete_1_t is an unconstrained tagged type that requires constructor
obj : Root.Classes.Concrete_1.Concrete_1_t :=
Root.Classes.Concrete_1.fConstructor (Argument => idx);
begin
aVector.pAppend (New_Item => obj);
end;
end loop;
-- Trying to clear the vector after all appends; this does not seem to work
aVector.pClear;
end Main;
Then, I have used gnatmem to check if I have any memory leak, showing the following:
Global information
------------------
Total number of allocations :779831
Total number of deallocations :5080
Final Water Mark (non freed mem) : 26.71 Megabytes
High Water Mark : 26.71 Megabytes
Allocation Root # 1
-------------------
Number of non freed allocations :764550
Final Water Mark (non freed mem) : 17.50 Megabytes
High Water Mark : 17.50 Megabytes
Backtrace :
??:0 ??
Allocation Root # 2
-------------------
Number of non freed allocations :5100
Final Water Mark (non freed mem) : 119.53 Kilobytes
High Water Mark : 119.53 Kilobytes
Backtrace :
a-cfinve.adb:220 root.vectors.polimorphicVector_pck.copy
Allocation Root # 3
-------------------
Number of non freed allocations :3390
Final Water Mark (non freed mem) : 7.78 Megabytes
High Water Mark : 7.78 Megabytes
Backtrace :
a-cfinve.adb:466 root.vectors.polimorphicVector_pck.find_index
Allocation Root # 4
-------------------
Number of non freed allocations :1710
Final Water Mark (non freed mem) : 1.32 Megabytes
High Water Mark : 1.32 Megabytes
Backtrace :
a-cfinve.adb:219 root.vectors.polimorphicVector_pck.copy
Allocation Root # 5
-------------------
Number of non freed allocations : 1
Final Water Mark (non freed mem) : 8 Bytes
High Water Mark : 8 Bytes
Backtrace :
??:0 system.stream_attributes.xdr.i_ssi
Why is it leaking? It can be due to the "=" that always return True?
You instantiate the container as Bounded:
Bounded => True);
Bounded containers are allocated on stack. This is also documented in the spec-file:
Bounded : Boolean := True;
-- If True, the containers are bounded; the initial capacity is the maximum
-- size, and heap allocation will be avoided. If False, the containers can
-- grow via heap allocation.