comp.lang.ada
 help / color / mirror / Atom feed
* Limited_Controlled types as 'out' arguments
@ 2003-07-30 11:31 Lutz Donnerhacke
  2003-07-30 12:22 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 11:31 UTC (permalink / raw)


I'm using an Limited_Controlled type as an 'out' parameter of a procedure.
While programming this procedure in question, I wonder how to Finalize the
object given as argument to the 'out' parameter.

------------------------------------------------------------------------
with Ada.Finalization;

package t1 is
   type Test is new Ada.Finalization.Limited_Controlled with record
      a : Character;
   end record;
   procedure Initialize(o : in out Test);
   procedure Finalize(o : in out Test);
   procedure Copy(to : out Test; from : Test);
end t1;
------------------------------------------------------------------------
with t1;
use t1;

procedure t is
   a, b, c : Test;
begin
   Copy(a, b);
   Copy(a, c);
end t;
------------------------------------------------------------------------
with Ada.Text_IO;
use Ada.Text_IO;

package body t1 is
   global : Character := '0';
   
   procedure Initialize(o : in out Test) is
   begin
      o.a := global;
      Put_Line("Initializing " & o.a);
      global := Character'Succ(global);
   end Initialize;
   
   procedure Finalize(o : in out Test) is
   begin
      Put_Line("Finalizing " & o.a);
   end Finalize;
   
   procedure Copy(to : out Test; from : Test) is
   begin
      to.a := global;
      Put_Line("Copying " & from.a & " to " & to.a);
      global := Character'Succ(global);
   end Copy;
end t1;
------------------------------------------------------------------------

This results in:
   Initializing 0
   Initializing 1
   Initializing 2
   Copying 1 to 3
   Copying 2 to 4
   Finalizing 2
   Finalizing 1
   Finalizing 4

Clearly, the variable 0 and 3 are never finalized. How implement I this
correctly (without refering to the rosen trick).



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 11:31 Limited_Controlled types as 'out' arguments Lutz Donnerhacke
@ 2003-07-30 12:22 ` Dmitry A. Kazakov
  2003-07-30 12:32   ` Lutz Donnerhacke
  2003-07-30 12:31 ` Matthew Heaney
  2003-07-30 12:37 ` Martin Dowie
  2 siblings, 1 reply; 25+ messages in thread
From: Dmitry A. Kazakov @ 2003-07-30 12:22 UTC (permalink / raw)


On Wed, 30 Jul 2003 11:31:03 +0000 (UTC), Lutz Donnerhacke
<lutz@iks-jena.de> wrote:

>I'm using an Limited_Controlled type as an 'out' parameter of a procedure.
>While programming this procedure in question, I wonder how to Finalize the
>object given as argument to the 'out' parameter.
>
>------------------------------------------------------------------------
>with Ada.Finalization;
>
>package t1 is
>   type Test is new Ada.Finalization.Limited_Controlled with record
>      a : Character;
>   end record;
>   procedure Initialize(o : in out Test);
>   procedure Finalize(o : in out Test);
>   procedure Copy(to : out Test; from : Test);
>end t1;
>------------------------------------------------------------------------
>with t1;
>use t1;
>
>procedure t is
>   a, b, c : Test;
>begin
>   Copy(a, b);
>   Copy(a, c);
>end t;

[...]

>This results in:
>   Initializing 0
>   Initializing 1
>   Initializing 2
>   Copying 1 to 3
>   Copying 2 to 4
>   Finalizing 2
>   Finalizing 1
>   Finalizing 4
>
>Clearly, the variable 0 and 3 are never finalized. How implement I this
>correctly (without refering to the rosen trick).

1. Why do you think that it is incorrect? Copy does not destruct the
target, so why should it call Finalize?

2. But if you still want something like that, then make Copy
class-wide:

type Test is new Ada.Finalization.Limited_Controlled with ...

procedure Destruct (This : in out Test);
procedure Construct (To : in out Test; From : Test);

procedure Copy (To : in out Test'Class; From : Test'Class) is
begin
   Destruct (To);
   Construct (To, From);
end Copy;

procedure Finalize (This : in out Test) is
begin
   Destruct (Test);
   -- Carefully here, when overriding Finalize!
   -- You will probably need a flag preventing
   -- multiple calls to Destruct upon finalization.
   -- Alternatively, you could refrain from calling parent's
   -- Finalize, but then you should ensure that
   -- Destruct does everything needed.
end Finalize;

Beware, true multiple dispatch is not supported in Ada. So if you want
to copy objects of different types you have to simulate MD.

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 11:31 Limited_Controlled types as 'out' arguments Lutz Donnerhacke
  2003-07-30 12:22 ` Dmitry A. Kazakov
@ 2003-07-30 12:31 ` Matthew Heaney
  2003-07-30 12:57   ` Lutz Donnerhacke
  2003-07-30 12:37 ` Martin Dowie
  2 siblings, 1 reply; 25+ messages in thread
From: Matthew Heaney @ 2003-07-30 12:31 UTC (permalink / raw)



"Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
news:slrnbifb3k.o6.lutz@taranis.iks-jena.de...
> I'm using an Limited_Controlled type as an 'out' parameter of a procedure.
> While programming this procedure in question, I wonder how to Finalize the
> object given as argument to the 'out' parameter.

Controlled types, like all tagged types, are passed by reference.

Three objects (a, b, c) are Initialize'd , and the same three objects are
Finalize'd.

Which objects do you think aren't being finalized?







^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 12:22 ` Dmitry A. Kazakov
@ 2003-07-30 12:32   ` Lutz Donnerhacke
  2003-07-30 14:24     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 12:32 UTC (permalink / raw)


* Dmitry A Kazakov wrote:
> On Wed, 30 Jul 2003 11:31:03 +0000 (UTC), Lutz Donnerhacke
>>   procedure Copy(to : out Test; from : Test);
>>
>>Clearly, the variable 0 and 3 are never finalized. How implement I this
>>correctly (without refering to the rosen trick).
>
> 1. Why do you think that it is incorrect? Copy does not destruct the
>    target, so why should it call Finalize?

In my implementation, the type Test contains an array_access, I have to
deallocate, before assigning a new value. I can not deallocate this access
variable, because the procedure Free (unchecked_deallocate) requires an
'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
before the first write.

In short: The former contents (despite discriminates) of an 'out' parameter
are not available inside the procedure. So the former contents are not
finalizable inside this procedure.

> procedure Copy (To : in out Test'Class; From : Test'Class) is
> begin
>    Destruct (To);
>    Construct (To, From);
> end Copy;

Fine, but try this with the prototype:
  procedure Copy (To : out Test'Class; From : Test'Class);

> Beware, true multiple dispatch is not supported in Ada. So if you want
> to copy objects of different types you have to simulate MD.

Wrong answer. Not every problem is MI related.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 11:31 Limited_Controlled types as 'out' arguments Lutz Donnerhacke
  2003-07-30 12:22 ` Dmitry A. Kazakov
  2003-07-30 12:31 ` Matthew Heaney
@ 2003-07-30 12:37 ` Martin Dowie
  2003-07-30 12:59   ` Lutz Donnerhacke
  2 siblings, 1 reply; 25+ messages in thread
From: Martin Dowie @ 2003-07-30 12:37 UTC (permalink / raw)


"Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
news:slrnbifb3k.o6.lutz@taranis.iks-jena.de...
> I'm using an Limited_Controlled type as an 'out' parameter of a procedure.
[snip]
>    procedure Copy(to : out Test; from : Test) is
>    begin
>       to.a := global;
>       Put_Line("Copying " & from.a & " to " & to.a);
>       global := Character'Succ(global);
>    end Copy;

Shouldn't this actually copy something out of 'from'?






^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 12:31 ` Matthew Heaney
@ 2003-07-30 12:57   ` Lutz Donnerhacke
  2003-07-30 13:47     ` Martin Dowie
  2003-07-30 17:06     ` Matthew Heaney
  0 siblings, 2 replies; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 12:57 UTC (permalink / raw)


* Matthew Heaney wrote:
> Controlled types, like all tagged types, are passed by reference.

'out' Parameters can't be read.

> Three objects (a, b, c) are Initialize'd , and the same three objects are
> Finalize'd.
> 
> Which objects do you think aren't being finalized?

Extended example:
------------------------------------------------------------------------
with Ada.Finalization;

package t1 is
   type Char_Access is access Character;
   type Test is new Ada.Finalization.Limited_Controlled with record
      a : Char_Access;
   end record;
   procedure Initialize(o : in out Test);
   procedure Finalize(o : in out Test);
   procedure Copy(to : out Test; from : Test);
end t1;
------------------------------------------------------------------------
with t1;
use t1;

procedure t is
   a, b, c : Test;
begin
   Copy(a, b);
   Copy(a, c);
end t;
------------------------------------------------------------------------
with Ada.Text_IO;
with System.Storage_Elements, System.Address_To_Access_Conversions;
with Unchecked_Deallocation;
use Ada.Text_IO;

package body t1 is
   procedure Debug (msg : String; p : Char_Access) is
      use System.Storage_Elements;
      package Convert is new System.Address_To_Access_Conversions(Character);
   begin
      Put_Line(msg &
        Integer_Address'Image(To_Integer(
            Convert.To_Address(Convert.Object_Pointer(p)))) &
        '(' & p.all & ')');
   end Debug;
   
   global : Character := '0';
   
   procedure Initialize(o : in out Test) is
   begin
      o.a := new Character'(global);
      Debug("Initializing", o.a);
      global := Character'Succ(global);
   end Initialize;
   
   procedure Finalize(o : in out Test) is
      procedure Free is new Unchecked_Deallocation(Character, Char_Access);
   begin
      Debug("Finalizing", o.a);
      Free(o.a);
   end Finalize;
   
   procedure Copy(to : out Test; from : Test) is
   begin
      to.a := new Character'(global);
      Debug("Copying from", from.a);
      Debug("Copying to  ", to.a);
      global := Character'Succ(global);
   end Copy;
end t1;
------------------------------------------------------------------------


Results in a beautiful memory leak:
   Initializing 134630832(0)
   Initializing 134630848(1)
   Initializing 134630864(2)
   Copying from 134630848(1)
   Copying to   134630880(3)
   Copying from 134630864(2)
   Copying to   134630896(4)
   Finalizing 134630864(2)
   Finalizing 134630848(1)
   Finalizing 134630896(4)

134630832 and 134630880 are never freed.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 12:37 ` Martin Dowie
@ 2003-07-30 12:59   ` Lutz Donnerhacke
  2003-07-30 13:41     ` Martin Dowie
  0 siblings, 1 reply; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 12:59 UTC (permalink / raw)


* Martin Dowie wrote:
> "Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
>>    procedure Copy(to : out Test; from : Test) is
>>    begin
>>       to.a := global;
>>       Put_Line("Copying " & from.a & " to " & to.a);
>>       global := Character'Succ(global);
>>    end Copy;
>
> Shouldn't this actually copy something out of 'from'?

For examples you cut your real world problem until it's small.
Yes, it's sufficent to call 'procedure example(a : out Test)'.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 12:59   ` Lutz Donnerhacke
@ 2003-07-30 13:41     ` Martin Dowie
  0 siblings, 0 replies; 25+ messages in thread
From: Martin Dowie @ 2003-07-30 13:41 UTC (permalink / raw)


"Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
news:slrnbifg8q.o6.lutz@taranis.iks-jena.de...
> * Martin Dowie wrote:
> > Shouldn't this actually copy something out of 'from'?
>
> For examples you cut your real world problem until it's small.
> Yes, it's sufficent to call 'procedure example(a : out Test)'.

Sorry, it just looked like confusion over 'where' the '0'&'3' values had
gone - and they had simply been overwitten.

But of course there a memory leak - it's here:

procedure Copy(to : out Test; from : Test) is
   begin
      to.a := new Character'(global);   ---- <<<<<<<<<

You've over writen what "to.a" did point to with something else.

Perhaps you meant "to.a.all := Global;"






^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 12:57   ` Lutz Donnerhacke
@ 2003-07-30 13:47     ` Martin Dowie
  2003-07-30 17:06     ` Matthew Heaney
  1 sibling, 0 replies; 25+ messages in thread
From: Martin Dowie @ 2003-07-30 13:47 UTC (permalink / raw)


>    procedure Debug (msg : String; p : Char_Access) is

Also, to demonstrate that it is the same 3 variables, don't use
the address of something inside, use the 'Address of the actual
variables.

   procedure Debug (Msg : String; P : System.Address) is
   ...
   Debug("Initializing", O'Address);

and then everything can be seen to be ok.







^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 12:32   ` Lutz Donnerhacke
@ 2003-07-30 14:24     ` Dmitry A. Kazakov
  2003-07-30 14:25       ` Lutz Donnerhacke
  0 siblings, 1 reply; 25+ messages in thread
From: Dmitry A. Kazakov @ 2003-07-30 14:24 UTC (permalink / raw)


On Wed, 30 Jul 2003 12:32:17 +0000 (UTC), Lutz Donnerhacke
<lutz@iks-jena.de> wrote:

>* Dmitry A Kazakov wrote:
>> On Wed, 30 Jul 2003 11:31:03 +0000 (UTC), Lutz Donnerhacke
>>>   procedure Copy(to : out Test; from : Test);
>>>
>>>Clearly, the variable 0 and 3 are never finalized. How implement I this
>>>correctly (without refering to the rosen trick).
>>
>> 1. Why do you think that it is incorrect? Copy does not destruct the
>>    target, so why should it call Finalize?
>
>In my implementation, the type Test contains an array_access, I have to
>deallocate, before assigning a new value. I can not deallocate this access
>variable, because the procedure Free (unchecked_deallocate) requires an
>'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
>before the first write.

You can in Ada 95.

>In short: The former contents (despite discriminates) of an 'out' parameter
>are not available inside the procedure. So the former contents are not
>finalizable inside this procedure.
>
>> procedure Copy (To : in out Test'Class; From : Test'Class) is
>> begin
>>    Destruct (To);
>>    Construct (To, From);
>> end Copy;
>
>Fine, but try this with the prototype:
>  procedure Copy (To : out Test'Class; From : Test'Class);

This compiles with GNAT:
-----------------------
with Ada.Finalization;

package A is
   type Int_Ptr is access Integer;
   type Test is new Ada.Finalization.Limited_Controlled with record
      Ptr : Int_Ptr;
   end record;
   procedure Destruct (To : in out Test);
   procedure Construct (To : in out Test; From : Test);
   procedure Copy (To : out Test'Class; From : Test'Class);
end A;
---------------------
with Ada.Finalization;
with Ada.Unchecked_Deallocation;

package body A is
   procedure Free is
      new Ada.Unchecked_Deallocation (Integer, Int_Ptr);
   procedure Destruct (To : in out Test) is
   begin
      Free (To.Ptr);
   end Destruct;
   
   procedure Construct (To : in out Test; From : Test) is
   begin
      To.Ptr := From.Ptr;
   end Construct;
   
   procedure Copy (To : out Test'Class; From : Test'Class) is
   begin
      Destruct (To);
      Construct (To, From);
   end Copy;
end A;

>> Beware, true multiple dispatch is not supported in Ada. So if you want
>> to copy objects of different types you have to simulate MD.
>
>Wrong answer. Not every problem is MI related.

MD /= MI. Multiple dispatch is when there are many controlling
arguments of different tags. Assignment / copy is a case. You have
source and target, and sometimes you want assign:

X : Local_String;
Y : Remote_String;

Copy (Y, X); -- Constraint_Error

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 14:24     ` Dmitry A. Kazakov
@ 2003-07-30 14:25       ` Lutz Donnerhacke
  2003-07-30 14:48         ` Dmitry A. Kazakov
                           ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 14:25 UTC (permalink / raw)


* Dmitry A Kazakov wrote:
> On Wed, 30 Jul 2003 12:32:17 +0000 (UTC), Lutz Donnerhacke
>>In my implementation, the type Test contains an array_access, I have to
>>deallocate, before assigning a new value. I can not deallocate this access
>>variable, because the procedure Free (unchecked_deallocate) requires an
>>'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
>>before the first write.
>
> You can in Ada 95.

Oops. Why? This is a clear data flow error, which should be avoided.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 14:25       ` Lutz Donnerhacke
@ 2003-07-30 14:48         ` Dmitry A. Kazakov
  2003-07-30 15:15           ` Lutz Donnerhacke
  2003-07-30 15:01         ` Vinzent Hoefler
  2003-07-30 15:52         ` Lutz Donnerhacke
  2 siblings, 1 reply; 25+ messages in thread
From: Dmitry A. Kazakov @ 2003-07-30 14:48 UTC (permalink / raw)


On Wed, 30 Jul 2003 14:25:46 +0000 (UTC), Lutz Donnerhacke
<lutz@iks-jena.de> wrote:

>* Dmitry A Kazakov wrote:
>> On Wed, 30 Jul 2003 12:32:17 +0000 (UTC), Lutz Donnerhacke
>>>In my implementation, the type Test contains an array_access, I have to
>>>deallocate, before assigning a new value. I can not deallocate this access
>>>variable, because the procedure Free (unchecked_deallocate) requires an
>>>'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
>>>before the first write.
>>
>> You can in Ada 95.
>
>Oops. Why? This is a clear data flow error, which should be avoided.

It is an interesting question. What could be alternatives

1. to leave "out" parameters uninitialized. This is bad.

2. to disallow reading from them, but then how to get discriminants?

2.a. to disallow reading before first write except for discriminants,
constraints and type tag. Well, how many pages would it take to
consistently describe something like that in ARM? (:-)) Add here is
some run-time checks burden.

2.b. return statement for "out"

   procedure Foo (X : out String; Y : Some'Class) is
   begin
      return
      (  X => "Any text",
         Y => Create_Some
      );
   end Foo;

looks awful, and after all how to implement unconstrained "out"
parameters?

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 14:25       ` Lutz Donnerhacke
  2003-07-30 14:48         ` Dmitry A. Kazakov
@ 2003-07-30 15:01         ` Vinzent Hoefler
  2003-07-30 15:16           ` Lutz Donnerhacke
  2003-07-30 15:52         ` Lutz Donnerhacke
  2 siblings, 1 reply; 25+ messages in thread
From: Vinzent Hoefler @ 2003-07-30 15:01 UTC (permalink / raw)


Lutz Donnerhacke wrote:

>* Dmitry A Kazakov wrote:
>
[reading "out"-Parameters]
>> You can in Ada 95.
>
>Oops. Why?

Convinience. Sometimes it avoids the temporary copy that would be
needed in Ada83. See the example below.

>This is a clear data flow error,

Not if you have updated the object inside the procedure before reading
it, consider this:

|   procedure Set_Timer_Limits (Input_Frequency : in Frequency;
|                               Limit           : in Min_Max;
|                               Timer           : out TxParm;
|                               In_Range        : out Boolean) is
|   begin
|      --  here the Timer object is not yet initialized, reading
|      --  would be a data flow error
|      Timer.Min := Clamp8254 (Input_Frequency / Limit.Max);
|      Timer.Max := Clamp8254 (Input_Frequency / Limit.Min);
|
|      --  but here we can simply read it without data flow error
|      --  or the need for a temporary copy
|      In_Range := ((Input_Frequency / Timer.Max) > Limit.Min) and
|                  ((Input_Frequency / Timer.Min) < Limit.Max);
|   end Set_Timer_Limits;


Vinzent.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 14:48         ` Dmitry A. Kazakov
@ 2003-07-30 15:15           ` Lutz Donnerhacke
  2003-07-31 10:26             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 15:15 UTC (permalink / raw)


* Dmitry A Kazakov wrote:
> On Wed, 30 Jul 2003 14:25:46 +0000 (UTC), Lutz Donnerhacke
>>* Dmitry A Kazakov wrote:
>>> On Wed, 30 Jul 2003 12:32:17 +0000 (UTC), Lutz Donnerhacke
>>>>In my implementation, the type Test contains an array_access, I have to
>>>>deallocate, before assigning a new value. I can not deallocate this access
>>>>variable, because the procedure Free (unchecked_deallocate) requires an
>>>>'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
>>>>before the first write.
>>>
>>> You can in Ada 95.
>>
>>Oops. Why? This is a clear data flow error, which should be avoided.
> 
> It is an interesting question. What could be alternatives
> 
> 1. to leave "out" parameters uninitialized. This is bad.

This is the most common implementation on most types. (most = unless you
define an Initialize procedure, default component data, or provide
initialization data)

> 2. to disallow reading from them, but then how to get discriminants?

Discriminants of 'out' types have mode 'in'. Always.

> 2.a. to disallow reading before first write except for discriminants,
> constraints and type tag.

Discriminants, ... can't be written on 'out' types.

> 2.b. return statement for "out"
> 
>    procedure Foo (X : out String; Y : Some'Class) is
>    begin
>       return
>       (  X => "Any text",
>          Y => Create_Some
>       );
>    end Foo;

No!

3) Finalize the current data of the 'limited out' parameter.
   Adjust the assigned data of the 'unlimited out' paramter after return.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 15:01         ` Vinzent Hoefler
@ 2003-07-30 15:16           ` Lutz Donnerhacke
  0 siblings, 0 replies; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 15:16 UTC (permalink / raw)


* Vinzent Hoefler wrote:
> Lutz Donnerhacke wrote:
>>* Dmitry A Kazakov wrote:
> [reading "out"-Parameters]
>>> You can in Ada 95.
>>
>>Oops. Why?
> 
> Convinience. Sometimes it avoids the temporary copy that would be
> needed in Ada83. See the example below.
> 
>>This is a clear data flow error,
> 
> Not if you have updated the object inside the procedure before reading
> it, consider this:
> 
>|   procedure Set_Timer_Limits (Input_Frequency : in Frequency;
>|                               Limit           : in Min_Max;
>|                               Timer           : out TxParm;
>|                               In_Range        : out Boolean) is
>|   begin
>|      --  here the Timer object is not yet initialized, reading
>|      --  would be a data flow error

Got it. This is the place, where a finalization like access have to be done.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 14:25       ` Lutz Donnerhacke
  2003-07-30 14:48         ` Dmitry A. Kazakov
  2003-07-30 15:01         ` Vinzent Hoefler
@ 2003-07-30 15:52         ` Lutz Donnerhacke
  2003-07-30 19:30           ` Randy Brukardt
  2 siblings, 1 reply; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-30 15:52 UTC (permalink / raw)


* Lutz Donnerhacke wrote:
> * Dmitry A Kazakov wrote:
>> On Wed, 30 Jul 2003 12:32:17 +0000 (UTC), Lutz Donnerhacke
>>>In my implementation, the type Test contains an array_access, I have to
>>>deallocate, before assigning a new value. I can not deallocate this access
>>>variable, because the procedure Free (unchecked_deallocate) requires an
>>>'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
>>>before the first write.
>>
>> You can in Ada 95.
> 
> Oops. Why? This is a clear data flow error, which should be avoided.

To stress this point even more. The approbriate counterpart using assignment
statments and controlled types result in:

------------------------------------------------------------------------
with Ada.Finalization;

package t1 is
   type Char_Access is access Character;
   type Test is new Ada.Finalization.Controlled with record
      a : Char_Access;
   end record;
   procedure Initialize(o : in out Test);
   procedure Finalize(o : in out Test);
   procedure Adjust(o : in out Test);
end t1;
------------------------------------------------------------------------
with t1;
use t1;

procedure t is
   a, b, c : Test;
begin
   a := b;
   a := c;
end t;
------------------------------------------------------------------------
with Ada.Text_IO;
with System.Storage_Elements, System.Address_To_Access_Conversions;
with Unchecked_Deallocation;
use Ada.Text_IO;

package body t1 is
   procedure Debug (msg : String; p : Char_Access) is
      use System.Storage_Elements;
      package Convert is new System.Address_To_Access_Conversions(Character);
   begin
      Put_Line(msg &
        Integer_Address'Image(To_Integer(
            Convert.To_Address(Convert.Object_Pointer(p)))) &
        '(' & p.all & ')');
   end Debug;
   
   global : Character := '0';
   
   procedure Initialize(o : in out Test) is
   begin
      o.a := new Character'(global);
      Debug("Initializing", o.a);
      global := Character'Succ(global);
   end Initialize;
   
   procedure Finalize(o : in out Test) is
      procedure Free is new Unchecked_Deallocation(Character, Char_Access);
   begin
      Debug("Finalizing", o.a);
      Free(o.a);
   end Finalize;
   
   procedure Adjust(o : in out Test) is
      procedure Free is new Unchecked_Deallocation(Character, Char_Access);
      tmp : Char_Access := new Character'(' '); -- occupy some memory
   begin
      Debug("Adjusting from", o.a);
      o.a := new Character'(o.a.all);
      Debug("Adjusting to  ", o.a);
      Free(tmp);
   end Adjust;
end t1;
------------------------------------------------------------------------

Results in:
  Initializing 134630032(0)
  Initializing 134630048(1)
  Initializing 134630064(2)
  Finalizing 134630032(0)
  Adjusting from 134630048(1)
  Adjusting to   134630080(1)
  Finalizing 134630080(1)
  Adjusting from 134630064(2)
  Adjusting to   134630032(2)
  Finalizing 134630064(2)
  Finalizing 134630048(1)
  Finalizing 134630032(2)

Despite the upthead argument "there are only three instances, so finalizing
them suffice", here are also only three instances, which are finalized before
assigment.

Trying it with an 'out' parameter
   procedure Set(o : out Test) is
   begin
      Debug("Setting from", o.a);
      o.a := new Character'(global);
      Debug("Setting to  ", o.a);
      global := Character'Succ(global);
   end Set;
[...]
with t1;
use t1;

procedure t is
   a, b, c : Test;
begin
   a := b;
   a := c;
   Set(a);
   Set(a);
end t;
------------------------------------------------------------------------

gives:
  Initializing 134630064(0)
  Initializing 134630080(1)
  Initializing 134630096(2)
  Finalizing 134630064(0)
  Adjusting from 134630080(1)
  Adjusting to   134630112(1)
  Finalizing 134630112(1)
  Adjusting from 134630096(2)
  Adjusting to   134630064(2)
  Setting from 134630064(2)
  Setting to   134630112(3)
  Setting from 134630112(3)
  Setting to   134630128(4)
  Finalizing 134630096(2)
  Finalizing 134630080(1)
  Finalizing 134630128(4)
  
which is clearly wrong in the same way.

So the only result of this can be: Do not provide 'out' Parameters to
controlled types in the same library unit.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 12:57   ` Lutz Donnerhacke
  2003-07-30 13:47     ` Martin Dowie
@ 2003-07-30 17:06     ` Matthew Heaney
  1 sibling, 0 replies; 25+ messages in thread
From: Matthew Heaney @ 2003-07-30 17:06 UTC (permalink / raw)


Lutz Donnerhacke <lutz@iks-jena.de> wrote in message news:<slrnbifg5p.o6.lutz@taranis.iks-jena.de>...
> * Matthew Heaney wrote:
> > Controlled types, like all tagged types, are passed by reference.
> 
> 'out' Parameters can't be read.

This statement is false.  

Controlled initialization for the object passed as the out parameter
of the call has already occured at the time of elaboration of the
object, which is prior to the call.

Controlled finalization of the object occurs when the scope containing
the declaration ends.

The issue of invokation of controlled operations is orthogonal to the
issue of whether the object is passed as an out parameter.

There is nothing wrong with your original example.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 15:52         ` Lutz Donnerhacke
@ 2003-07-30 19:30           ` Randy Brukardt
  2003-07-31  7:43             ` Lutz Donnerhacke
  0 siblings, 1 reply; 25+ messages in thread
From: Randy Brukardt @ 2003-07-30 19:30 UTC (permalink / raw)


"Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
news:slrnbifqdp.o6.lutz@taranis.iks-jena.de...
...
> which is clearly wrong in the same way.

Of course. "in out" and "out" parameters for tagged types (and most other
types as well) are equivalent. Consider the lack of an "in" to be a comment
to the caller, not to the author of the subprogram.

There is never an "uninitialized" tagged object. Some of the components may
not be initialized (esp. if the type isn't controlled), but the object as a
whole is initialized. If it wasn't, the tag wouldn't be set, which would
make even membership operations impossible.

> So the only result of this can be: Do not provide 'out' Parameters to
> controlled types in the same library unit.

No, just realize that "out" is the same as "in out" as far as the
implementation of a routine is concerned. But it still can provide useful
information to the caller.

                      Randy.






^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 19:30           ` Randy Brukardt
@ 2003-07-31  7:43             ` Lutz Donnerhacke
  0 siblings, 0 replies; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-31  7:43 UTC (permalink / raw)


* Randy Brukardt wrote:
> "Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
>> which is clearly wrong in the same way.
> 
> Of course. "in out" and "out" parameters for tagged types (and most other
> types as well) are equivalent. Consider the lack of an "in" to be a comment
> to the caller, not to the author of the subprogram.

I thought a call "xxx(my)" to "procedure xxx (a : out Test)" is very similar
to "my := xxx", if a "function xxx return Test" exists.

This idea is wrong.

> not be initialized (esp. if the type isn't controlled), but the object as a
> whole is initialized. If it wasn't, the tag wouldn't be set, which would
> make even membership operations impossible.

Ack for discriminants, tags, etc.
Nack for private data.

So the consequence is: If you pass a controlled type as an 'out' paramenter
in the type defining library unit, provide sufficient initialization for all
private data, otherwise you can't distiguish uninitalized garbage from real
data.

>> So the only result of this can be: Do not provide 'out' Parameters to
>> controlled types in the same library unit.
>
> No, just realize that "out" is the same as "in out" as far as the
> implementation of a routine is concerned. But it still can provide useful
> information to the caller.

I'm going to see this, but I'm still confused.



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-30 15:15           ` Lutz Donnerhacke
@ 2003-07-31 10:26             ` Dmitry A. Kazakov
  2003-07-31 10:54               ` Lutz Donnerhacke
  0 siblings, 1 reply; 25+ messages in thread
From: Dmitry A. Kazakov @ 2003-07-31 10:26 UTC (permalink / raw)


On Wed, 30 Jul 2003 15:15:09 +0000 (UTC), Lutz Donnerhacke
<lutz@iks-jena.de> wrote:

>* Dmitry A Kazakov wrote:
>> On Wed, 30 Jul 2003 14:25:46 +0000 (UTC), Lutz Donnerhacke
>>>* Dmitry A Kazakov wrote:
>>>> On Wed, 30 Jul 2003 12:32:17 +0000 (UTC), Lutz Donnerhacke
>>>>>In my implementation, the type Test contains an array_access, I have to
>>>>>deallocate, before assigning a new value. I can not deallocate this access
>>>>>variable, because the procedure Free (unchecked_deallocate) requires an
>>>>>'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
>>>>>before the first write.
>>>>
>>>> You can in Ada 95.
>>>
>>>Oops. Why? This is a clear data flow error, which should be avoided.
>> 
>> It is an interesting question. What could be alternatives
>> 
>> 1. to leave "out" parameters uninitialized. This is bad.
>
>This is the most common implementation on most types. (most = unless you
>define an Initialize procedure, default component data, or provide
>initialization data)

No they all are initialized, but probably with a garbage. (:-))

A really uninialized object is *(cast *) malloc (). Fortunately, we
have no this evil in Ada.

>> 2. to disallow reading from them, but then how to get discriminants?
>
>Discriminants of 'out' types have mode 'in'. Always.

Not always:

type A (I : Integer := 10) is null record;   
procedure Foo (X : out A) is
begin
   X := (I => 5); -- Change the discriminant
end Foo;

>3) Finalize the current data of the 'limited out' parameter.
>   Adjust the assigned data of the 'unlimited out' paramter after return.

It would be inconsistent. Adjust is called after a raw copy is made,
your subprogram uses a valid type interface instead. And you better
don't do it after Finalize [+ other destructors] were called. Consider
a task object as a member of your limited type.

What you actually describe is a copy constructor, not a subroutine.

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-31 10:26             ` Dmitry A. Kazakov
@ 2003-07-31 10:54               ` Lutz Donnerhacke
  2003-07-31 11:50                 ` Dmitry A. Kazakov
  2003-07-31 17:51                 ` Randy Brukardt
  0 siblings, 2 replies; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-31 10:54 UTC (permalink / raw)


* Dmitry A Kazakov wrote:
>>> 1. to leave "out" parameters uninitialized. This is bad.
>>
>>This is the most common implementation on most types. (most = unless you
>>define an Initialize procedure, default component data, or provide
>>initialization data)
>
> No they all are initialized, but probably with a garbage. (:-))

It's not that funny, if you need those data to manage ressources. Managing
data which is possibly garbage is very hard.

>>Discriminants of 'out' types have mode 'in'. Always.
>
> Not always:
>
> type A (I : Integer := 10) is null record;

Ok.

>>3) Finalize the current data of the 'limited out' parameter.
>>   Adjust the assigned data of the 'unlimited out' paramter after return.
>
> It would be inconsistent. Adjust is called after a raw copy is made,
> your subprogram uses a valid type interface instead. And you better
> don't do it after Finalize [+ other destructors] were called. Consider
> a task object as a member of your limited type.

I still do not get it completely.

------------------------------------------------------------------------
with Ada.Finalization;

package t1 is
   type Char_Access is access Character;
   type Test is new Ada.Finalization.Limited_Controlled with record
      a : Char_Access;
   end record;
   procedure Initialize(o : in out Test);
   procedure Finalize(o : in out Test);
   procedure Set(o1, o2 : out Test; i : Test);
end t1;
------------------------------------------------------------------------
with Ada.Text_IO;
with System.Storage_Elements, System.Address_To_Access_Conversions;
with Unchecked_Deallocation;
use Ada.Text_IO;

package body t1 is
   procedure Debug (msg : String; p : Char_Access) is
      use System.Storage_Elements;
      package Convert is new System.Address_To_Access_Conversions(Character);
   begin
      Put_Line(msg &
        Integer_Address'Image(To_Integer(
            Convert.To_Address(Convert.Object_Pointer(p)))) &
        '(' & p.all & ')');
   end Debug;
   
   global : Character := '0';
   
   procedure Initialize(o : in out Test) is
   begin
      o.a := new Character'(global);
      Debug("Initializing", o.a);
      global := Character'Succ(global);
   end Initialize;
   
   procedure Free is new Unchecked_Deallocation(Character, Char_Access);
   procedure Finalize(o : in out Test) is
   begin
      Debug("Finalizing  ", o.a);
      Free(o.a);
   end Finalize;
   
   procedure Set(o1, o2 : out Test; i : Test) is
   begin
      Debug("Setting from", i.a);
      Debug("Setting o1  ", o1.a);
      Debug("Setting o2  ", o2.a);
      Finalize(o1);
      Finalize(o2);
      
      o1.a := new Character'(global);
      Debug("Setting to1 ", o1.a);
      global := Character'Succ(global);

      o2.a := new Character'(i.a.all);
      Debug("Setting to2 ", o2.a);
   end Set;
end t1;
------------------------------------------------------------------------
with t1;
use t1;

procedure t is
   a, b : Test;
begin
   Set(a, a, b);
end t;
------------------------------------------------------------------------

Results in:
Initializing 134630800(0)
Initializing 134630816(1)
Setting from 134630816(1)
Setting o1   134630800(0)
Setting o2   134630800(0)
Finalizing   134630800(0)
raised PROGRAM_ERROR : t1.adb:14
Finalizing   134630816(1)

I'am mad?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-31 10:54               ` Lutz Donnerhacke
@ 2003-07-31 11:50                 ` Dmitry A. Kazakov
  2003-07-31 12:19                   ` Lutz Donnerhacke
  2003-07-31 17:51                 ` Randy Brukardt
  1 sibling, 1 reply; 25+ messages in thread
From: Dmitry A. Kazakov @ 2003-07-31 11:50 UTC (permalink / raw)


On Thu, 31 Jul 2003 10:54:44 +0000 (UTC), Lutz Donnerhacke
<lutz@iks-jena.de> wrote:

>* Dmitry A Kazakov wrote:
>>>> 1. to leave "out" parameters uninitialized. This is bad.
>>>
>>>This is the most common implementation on most types. (most = unless you
>>>define an Initialize procedure, default component data, or provide
>>>initialization data)
>>
>> No they all are initialized, but probably with a garbage. (:-))
>
>It's not that funny, if you need those data to manage ressources. Managing
>data which is possibly garbage is very hard.

The point is that formally the constructor exists, though does
nothing. So everything is initialized. You might be just unsatisfied
with the way of a particular initialization is done. Well, I was alone
against chorus chanting "we do not need user constructors for all
types". Wellcome in club. (:-))

>>>3) Finalize the current data of the 'limited out' parameter.
>>>   Adjust the assigned data of the 'unlimited out' paramter after return.
>>
>> It would be inconsistent. Adjust is called after a raw copy is made,
>> your subprogram uses a valid type interface instead. And you better
>> don't do it after Finalize [+ other destructors] were called. Consider
>> a task object as a member of your limited type.
>
>I still do not get it completely.
>
>------------------------------------------------------------------------
>with Ada.Finalization;
>
>package t1 is
>   type Char_Access is access Character;
>   type Test is new Ada.Finalization.Limited_Controlled with record
>      a : Char_Access;
>   end record;
>   procedure Initialize(o : in out Test);
>   procedure Finalize(o : in out Test);
>   procedure Set(o1, o2 : out Test; i : Test);
>end t1;
>------------------------------------------------------------------------
>with Ada.Text_IO;
>with System.Storage_Elements, System.Address_To_Access_Conversions;
>with Unchecked_Deallocation;
>use Ada.Text_IO;
>
>package body t1 is
>   procedure Debug (msg : String; p : Char_Access) is
>      use System.Storage_Elements;
>      package Convert is new System.Address_To_Access_Conversions(Character);
>   begin
>      Put_Line(msg &
>        Integer_Address'Image(To_Integer(
>            Convert.To_Address(Convert.Object_Pointer(p)))) &
>        '(' & p.all & ')');
>   end Debug;
>   
>   global : Character := '0';
>   
>   procedure Initialize(o : in out Test) is
>   begin
>      o.a := new Character'(global);
>      Debug("Initializing", o.a);
>      global := Character'Succ(global);
>   end Initialize;
>   
>   procedure Free is new Unchecked_Deallocation(Character, Char_Access);
>   procedure Finalize(o : in out Test) is
>   begin
>      Debug("Finalizing  ", o.a);
>      Free(o.a);
>   end Finalize;
>   
>   procedure Set(o1, o2 : out Test; i : Test) is
>   begin
>      Debug("Setting from", i.a);
>      Debug("Setting o1  ", o1.a);
>      Debug("Setting o2  ", o2.a);
>      Finalize(o1);
>      Finalize(o2);
>      
>      o1.a := new Character'(global);
>      Debug("Setting to1 ", o1.a);
>      global := Character'Succ(global);
>
>      o2.a := new Character'(i.a.all);
>      Debug("Setting to2 ", o2.a);
>   end Set;
>end t1;
>------------------------------------------------------------------------
>with t1;
>use t1;
>
>procedure t is
>   a, b : Test;
>begin
>   Set(a, a, b);
>end t;
>------------------------------------------------------------------------
>
>Results in:
>Initializing 134630800(0)
>Initializing 134630816(1)
>Setting from 134630816(1)
>Setting o1   134630800(0)
>Setting o2   134630800(0)
>Finalizing   134630800(0)
>raised PROGRAM_ERROR : t1.adb:14
>Finalizing   134630816(1)
>
>I'am mad?

Sort of, if you are calling Finalize from a normal subprogram! (:-))
As for error, you call Set (a, a, b); which finalizes a twice! It is a
language design fault that a destructor can be called explicitly. Your
example shows why.

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-31 11:50                 ` Dmitry A. Kazakov
@ 2003-07-31 12:19                   ` Lutz Donnerhacke
  2003-07-31 13:15                     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 25+ messages in thread
From: Lutz Donnerhacke @ 2003-07-31 12:19 UTC (permalink / raw)


* Dmitry A Kazakov wrote:
> On Thu, 31 Jul 2003 10:54:44 +0000 (UTC), Lutz Donnerhacke
>>   procedure Set(o1, o2 : out Test; i : Test) is
>>   begin
>>      Debug("Setting from", i.a);
>>      Debug("Setting o1  ", o1.a);
>>      Debug("Setting o2  ", o2.a);
>>      Finalize(o1);
>>      Finalize(o2);
>>      
>>      o1.a := new Character'(global);
>>      Debug("Setting to1 ", o1.a);
>>      global := Character'Succ(global);
>>
>>      o2.a := new Character'(i.a.all);
>>      Debug("Setting to2 ", o2.a);
>>   end Set;
> 
> Sort of, if you are calling Finalize from a normal subprogram! (:-))
> As for error, you call Set (a, a, b); which finalizes a twice! It is a
> language design fault that a destructor can be called explicitly. Your
> example shows why.

Changing the "Finalize" calls to "Free" causes the same effect.
So the main point is: How to manage resources correctly?

   procedure Set(o1, o2 : out Test; i : Test) is
   begin
      Debug("Setting from", i.a);
      if o1'Address /= o2'Address then
         Debug("Setting o1  ", o1.a);
         Free(o1.a);

         o1.a := new Character'(global);
         Debug("Setting to1 ", o1.a);
         global := Character'Succ(global);
      end if;

      Debug("Setting o2  ", o2.a);
      Free(o2.a);
      o2.a := new Character'(i.a.all);
      Debug("Setting to2 ", o2.a);
   end Set;

GNA!



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-31 12:19                   ` Lutz Donnerhacke
@ 2003-07-31 13:15                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 25+ messages in thread
From: Dmitry A. Kazakov @ 2003-07-31 13:15 UTC (permalink / raw)


On Thu, 31 Jul 2003 12:19:17 +0000 (UTC), Lutz Donnerhacke
<lutz@iks-jena.de> wrote:

>* Dmitry A Kazakov wrote:
>> On Thu, 31 Jul 2003 10:54:44 +0000 (UTC), Lutz Donnerhacke
>>>   procedure Set(o1, o2 : out Test; i : Test) is
>>>   begin
>>>      Debug("Setting from", i.a);
>>>      Debug("Setting o1  ", o1.a);
>>>      Debug("Setting o2  ", o2.a);
>>>      Finalize(o1);
>>>      Finalize(o2);
>>>      
>>>      o1.a := new Character'(global);
>>>      Debug("Setting to1 ", o1.a);
>>>      global := Character'Succ(global);
>>>
>>>      o2.a := new Character'(i.a.all);
>>>      Debug("Setting to2 ", o2.a);
>>>   end Set;
>> 
>> Sort of, if you are calling Finalize from a normal subprogram! (:-))
>> As for error, you call Set (a, a, b); which finalizes a twice! It is a
>> language design fault that a destructor can be called explicitly. Your
>> example shows why.
>
>Changing the "Finalize" calls to "Free" causes the same effect.
>So the main point is: How to manage resources correctly?

What do you mean? Aliasing problem or assignment of limited types?
Anyway what should not be confused is that assignment, copy
constructor, copy procedure, all are very different things.

>   procedure Set(o1, o2 : out Test; i : Test) is
>   begin
>      Debug("Setting from", i.a);
>      if o1'Address /= o2'Address then
>         Debug("Setting o1  ", o1.a);
>         Free(o1.a);
>
>         o1.a := new Character'(global);
>         Debug("Setting to1 ", o1.a);
>         global := Character'Succ(global);
>      end if;
>
>      Debug("Setting o2  ", o2.a);
>      Free(o2.a);
>      o2.a := new Character'(i.a.all);
>      Debug("Setting to2 ", o2.a);
>   end Set;
>
>GNA!

This should work.

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Limited_Controlled types as 'out' arguments
  2003-07-31 10:54               ` Lutz Donnerhacke
  2003-07-31 11:50                 ` Dmitry A. Kazakov
@ 2003-07-31 17:51                 ` Randy Brukardt
  1 sibling, 0 replies; 25+ messages in thread
From: Randy Brukardt @ 2003-07-31 17:51 UTC (permalink / raw)


"Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
news:slrnbihtb3.2j7.lutz@taranis.iks-jena.de...
...
> Results in:
> Initializing 134630800(0)
> Initializing 134630816(1)
> Setting from 134630816(1)
> Setting o1   134630800(0)
> Setting o2   134630800(0)
> Finalizing   134630800(0)
> raised PROGRAM_ERROR : t1.adb:14
> Finalizing   134630816(1)
>
> I'am mad?

Yes. :-)

Finalize routines always have to be written to work on an already finalized
object. There are variety of ways for extra Finalize calls to occur even
without any explicit ones. So your Finalize needs to be something like:

   procedure Finalize(o : in out Test) is
   begin
      if o.a /= null then
        Debug("Finalizing  ", o.a);
        Free(o.a);
      -- else already finalized.
      end if;
   end Finalize;

Otherwise, you're freeing an already freed object. This is discussed in the
AARM:
    http://www.adaic.org/standards/95aarm/html/AA-7-6-1.html
See the note at paragraph 24 and the following discussion.

                        Randy.






^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2003-07-31 17:51 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-30 11:31 Limited_Controlled types as 'out' arguments Lutz Donnerhacke
2003-07-30 12:22 ` Dmitry A. Kazakov
2003-07-30 12:32   ` Lutz Donnerhacke
2003-07-30 14:24     ` Dmitry A. Kazakov
2003-07-30 14:25       ` Lutz Donnerhacke
2003-07-30 14:48         ` Dmitry A. Kazakov
2003-07-30 15:15           ` Lutz Donnerhacke
2003-07-31 10:26             ` Dmitry A. Kazakov
2003-07-31 10:54               ` Lutz Donnerhacke
2003-07-31 11:50                 ` Dmitry A. Kazakov
2003-07-31 12:19                   ` Lutz Donnerhacke
2003-07-31 13:15                     ` Dmitry A. Kazakov
2003-07-31 17:51                 ` Randy Brukardt
2003-07-30 15:01         ` Vinzent Hoefler
2003-07-30 15:16           ` Lutz Donnerhacke
2003-07-30 15:52         ` Lutz Donnerhacke
2003-07-30 19:30           ` Randy Brukardt
2003-07-31  7:43             ` Lutz Donnerhacke
2003-07-30 12:31 ` Matthew Heaney
2003-07-30 12:57   ` Lutz Donnerhacke
2003-07-30 13:47     ` Martin Dowie
2003-07-30 17:06     ` Matthew Heaney
2003-07-30 12:37 ` Martin Dowie
2003-07-30 12:59   ` Lutz Donnerhacke
2003-07-30 13:41     ` Martin Dowie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox