Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Unchecked_Deallocation with tagged class type.

80 views
Skip to first unread message

Blady

unread,
Nov 14, 2023, 4:11:23 PM11/14/23
to
Hello,

The following code present a Finalize procedure with a parameter of
access tagged class type in order to deallocate the memory of the given
parameter from the root tagged type TTA and his children.
The same for TTB which is inherited from TTA. But this Finalize call
Finalize of TTA.
It may be not the best idea.
But let's see:

with Ada.Unchecked_Deallocation;
procedure test_20231113_free_tag is

type TTA is tagged record
AA : Integer;
end record;
type ATTA is access all TTA;
type CATTA is access all TTA'Class;
procedure Finalize (O : in out CATTA) is
procedure Free is new Ada.Unchecked_Deallocation (TTA, ATTA);
begin
Free (ATTA (O));
end Finalize;

type TTB is new TTA with record
BB : Integer;
end record;
type ATTB is access all TTB;
type CATTB is access all TTB'Class;
procedure Finalize (O : in out CATTB) is
begin
Finalize (CATTA (O));
end Finalize;

OA : CATTA := new TTA;
OB : CATTB := new TTB;

begin
Finalize (OA);
Finalize (OB);
end test_20231113_free_tag;

The procedure Free is the instanciation of Unchecked_Deallocation with
the tagged type TTA.
Thus the call "Finalize (OA);" deallocate the memory of object OA of
type access class TTA.

But what does "Finalize (OB);"?
What is the memory deallocate of object OB of type TTB?

Thanks, Pascal.


Dmitry A. Kazakov

unread,
Nov 14, 2023, 5:43:03 PM11/14/23
to
Crashes your program. It is a bug. You should instantiate
Unchecked_Deallocation with class-wide type if you pass a class-wide
pointer.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Blady

unread,
Nov 15, 2023, 3:26:11 PM11/15/23
to
Le 14/11/2023 à 23:42, Dmitry A. Kazakov a écrit :
>> But what does "Finalize (OB);"?
>
> Crashes your program. It is a bug. You should instantiate
> Unchecked_Deallocation with class-wide type if you pass a class-wide
> pointer.

Thanks, I haven't considered this possibility.
Note: the previous program built with GNAT FSF 13.2.0 ran without exception.

I've changed:
with Ada.Unchecked_Deallocation;
procedure test_20231113_free_class is

type TTA is tagged record
AA : Integer;
end record;
type ATTA is access all TTA;
type CATTA is access all TTA'Class;
procedure Finalize (O : in out CATTA) is
procedure Free is new Ada.Unchecked_Deallocation (TTA'Class, CATTA);
begin
Free (O);
end Finalize;

type TTB is new TTA with record
BB : Integer;
end record;
type ATTB is access all TTB;
type CATTB is access all TTB'Class;
procedure Finalize (O : in out CATTB) is
begin
Finalize (CATTA (O));
end Finalize;

OA : CATTA := new TTA;
OB : CATTB := new TTB;

begin
Finalize (OA);
Finalize (OB);
end test_20231113_free_class;

It runs without exception.
One question remains about "Finalize (OB);":
Which memory size is deallocated TTA'Size or TTB'Size?

Thanks, Pascal.



Dmitry A. Kazakov

unread,
Nov 15, 2023, 4:17:38 PM11/15/23
to
It is a wrong question. The implementation of the pool may ignore size
using the block size instead. Furthermore T'Size is not necessarily the
size actually allocated.

Regarding Unchecked_Deallocation instantiated with a pointer to a
class-wide object, consider it dispatching on the target object tag.
Thus you can deallocate any object using any instance of
Unchecked_Deallocation for any class-wide parent of, interfaces included.

So Finalize (OB) is OK.

Blady

unread,
Nov 16, 2023, 3:29:20 PM11/16/23
to
Le 15/11/2023 à 22:17, Dmitry A. Kazakov a écrit :
> On 2023-11-15 21:26, Blady wrote:
>> Le 14/11/2023 à 23:42, Dmitry A. Kazakov a écrit :
>>>> But what does "Finalize (OB);"?
<...>
> Regarding Unchecked_Deallocation instantiated with a pointer to a
> class-wide object, consider it dispatching on the target object tag.
> Thus you can deallocate any object using any instance of
> Unchecked_Deallocation for any class-wide parent of, interfaces included.
>
> So Finalize (OB) is OK.
>

Thanks, yes, the instanciation of Unchecked_Deallocation seemed to
indicate that but I was not able to confirm it from the Ada RM.
A mention in Ada RM 13.11.2 Unchecked Storage Deallocation of that
particular possibility would be valuable.

Regards, Pascal.

PS: after a quick search, I found also a smart answer with a full
example from Simon:
https://stackoverflow.com/questions/64951954/how-can-i-do-an-unchecked-deallocation-of-abstract-classes-in-ada

AdaMagica

unread,
Nov 17, 2023, 8:12:25 AM11/17/23
to
Blady schrieb am Donnerstag, 16. November 2023 um 21:29:20 UTC+1:
> Thanks, yes, the instanciation of Unchecked_Deallocation seemed to
> indicate that but I was not able to confirm it from the Ada RM.
> A mention in Ada RM 13.11.2 Unchecked Storage Deallocation of that
> particular possibility would be valuable.

type Object(<>) is limited private;

The box here denotes unknown discriminants, i.e. indefinite types - these include task types;
limited is "assume the worst" => i.e. any type may be used as actual type for this formal type.

AdaMagica

unread,
Nov 17, 2023, 8:13:44 AM11/17/23
to
AdaMagica schrieb am Freitag, 17. November 2023 um 14:12:25 UTC+1:
> Blady schrieb am Donnerstag, 16. November 2023 um 21:29:20 UTC+1:
> > Thanks, yes, the instanciation of Unchecked_Deallocation seemed to
> > indicate that but I was not able to confirm it from the Ada RM.
> > A mention in Ada RM 13.11.2 Unchecked Storage Deallocation of that
> > particular possibility would be valuable.
> type Object(<>) is limited private;
>
> The box here denotes unknown discriminants, i.e. indefinite types - these include task types;
nonsense - I mean class types
Message has been deleted
0 new messages