comp.lang.ada
 help / color / mirror / Atom feed
* unexpected behaviour of finalize
@ 2008-04-04  9:33 stefan-lucks
  2008-04-04 16:08 ` Adam Beneschan
  0 siblings, 1 reply; 7+ messages in thread
From: stefan-lucks @ 2008-04-04  9:33 UTC (permalink / raw)


Hi,

I have written a little program to demonstrate finalisation. The idea is 
to locally declare a singelton object of a class derived from 
Ada.Finalization.Limited_Controlled, and to override the Finalize method. 
When the sigelton object leaves scope, Finalize than cleans up whatever 
needs to be cleaned up. At a first look this appeared to work nicely. But 
when done in a recursive subprogram, Finalize rather unexpectedly seems to 
always read the local parameters of the innermost scope. 

Here is a test case:

---begin fin_test_case.adb

with Ada.Text_IO, Ada.Finalization;

procedure Fin_Test_Case is
   type Fin is new Ada.Finalization.Limited_Controlled with null record;

   procedure Do_Something (I: Natural) is

      type My_Fin is new Fin with null record;

      overriding procedure Finalize(Self: in out My_Fin) is
        S: String := Natural'Image(I);
      begin
         Ada.Text_IO.Put_Line("  Do_Something Finalization " & S);
      end Finalize;

      Singleton: My_Fin;

   begin -- Do_Something
      Ada.Text_IO.Put_Line("  I = " & Natural'Image(I));
      if I>0 then
         Do_Something(I-1);
         Do_Something(I-1);
      end if;
   end Do_Something;

begin
   Ada.Text_IO.Put_Line("Start Do_Something (2)");
   Do_Something(2);
   Ada.Text_IO.Put_Line("Stop Do_Something (2)");
end Fin_Test_Case;

---end fin_test_case.adb

This is what I got:

---begin output

Start Do_Something (2)
  I =  2
  I =  1
  I =  0
  Do_Something Finalization  0
  I =  0
  Do_Something Finalization  0
  Do_Something Finalization  0
  I =  1
  I =  0
  Do_Something Finalization  0
  I =  0
  Do_Something Finalization  0
  Do_Something Finalization  0
  Do_Something Finalization  0
Stop Do_Something (2)

---end output

Somehow, the local parameter I is always 0 when finalize is called. What I 
expected was the following:

---begin expected output

Start Do_Something (2)
  I =  2
  I =  1
  I =  0
  Do_Something Finalization  0
  I =  0
  Do_Something Finalization  0
  Do_Something Finalization  1
  I =  1
  I =  0
  Do_Something Finalization  0
  I =  0
  Do_Something Finalization  0
  Do_Something Finalization  1
  Do_Something Finalization  2
Stop Do_Something (2)

---end expected output

Now, is my expectation wrong? Or is this a compiler bug? I am using
GNAT GPL 2007 (20070405-41).

So long

Stefan



-- 
------ Stefan Lucks   --  Bauhaus-University Weimar  --   Germany  ------
               Stefan dot Lucks at uni minus weimar dot de
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------




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

* Re: unexpected behaviour of finalize
  2008-04-04  9:33 unexpected behaviour of finalize stefan-lucks
@ 2008-04-04 16:08 ` Adam Beneschan
  2008-04-04 17:34   ` george.priv
                     ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Adam Beneschan @ 2008-04-04 16:08 UTC (permalink / raw)


On Apr 4, 2:33 am, stefan-lu...@see.the.signature wrote:
> Hi,
>
> I have written a little program to demonstrate finalisation. The idea is
> to locally declare a singelton object of a class derived from
> Ada.Finalization.Limited_Controlled, and to override the Finalize method.
> When the sigelton object leaves scope, Finalize than cleans up whatever
> needs to be cleaned up. At a first look this appeared to work nicely. But
> when done in a recursive subprogram, Finalize rather unexpectedly seems to
> always read the local parameters of the innermost scope.
>
> Here is a test case:
>
> ---begin fin_test_case.adb
>
> with Ada.Text_IO, Ada.Finalization;
>
> procedure Fin_Test_Case is
>    type Fin is new Ada.Finalization.Limited_Controlled with null record;
>
>    procedure Do_Something (I: Natural) is
>
>       type My_Fin is new Fin with null record;
>
>       overriding procedure Finalize(Self: in out My_Fin) is
>         S: String := Natural'Image(I);
>       begin
>          Ada.Text_IO.Put_Line("  Do_Something Finalization " & S);
>       end Finalize;
>
>       Singleton: My_Fin;
>
>    begin -- Do_Something
>       Ada.Text_IO.Put_Line("  I = " & Natural'Image(I));
>       if I>0 then
>          Do_Something(I-1);
>          Do_Something(I-1);
>       end if;
>    end Do_Something;
>
> begin
>    Ada.Text_IO.Put_Line("Start Do_Something (2)");
>    Do_Something(2);
>    Ada.Text_IO.Put_Line("Stop Do_Something (2)");
> end Fin_Test_Case;
>
> ---end fin_test_case.adb
>
> This is what I got:
>
> ---begin output
>
> Start Do_Something (2)
>   I =  2
>   I =  1
>   I =  0
>   Do_Something Finalization  0
>   I =  0
>   Do_Something Finalization  0
>   Do_Something Finalization  0
>   I =  1
>   I =  0
>   Do_Something Finalization  0
>   I =  0
>   Do_Something Finalization  0
>   Do_Something Finalization  0
>   Do_Something Finalization  0
> Stop Do_Something (2)
>
> ---end output
>
> Somehow, the local parameter I is always 0 when finalize is called. What I
> expected was the following:
>
> ---begin expected output
>
> Start Do_Something (2)
>   I =  2
>   I =  1
>   I =  0
>   Do_Something Finalization  0
>   I =  0
>   Do_Something Finalization  0
>   Do_Something Finalization  1
>   I =  1
>   I =  0
>   Do_Something Finalization  0
>   I =  0
>   Do_Something Finalization  0
>   Do_Something Finalization  1
>   Do_Something Finalization  2
> Stop Do_Something (2)
>
> ---end expected output
>
> Now, is my expectation wrong? Or is this a compiler bug? I am using
> GNAT GPL 2007 (20070405-41).

This looks like a pretty clear compiler bug, especially since by the
time Finalize is called by the outermost Do_Something, it's using, for
the value of I, the parameter from a Do_Something call that is no
longer active.  It shouldn't be hard to modify this slightly, using
(say) a string or record as a parameter to Do_Something, to create a
test where utter garbage is displayed; then it would be clearer that
this is a compiler bug.

                                   -- Adam



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

* Re: unexpected behaviour of finalize
  2008-04-04 16:08 ` Adam Beneschan
@ 2008-04-04 17:34   ` george.priv
  2008-04-04 17:38   ` george.priv
  2008-04-04 17:51   ` stefan-lucks
  2 siblings, 0 replies; 7+ messages in thread
From: george.priv @ 2008-04-04 17:34 UTC (permalink / raw)


On Apr 4, 12:08 pm, Adam Beneschan <a...@irvine.com> wrote:
> On Apr 4, 2:33 am, stefan-lu...@see.the.signature wrote:
>
>
>
> > Hi,
>
> > I have written a little program to demonstrate finalisation. The idea is
> > to locally declare a singelton object of a class derived from
> > Ada.Finalization.Limited_Controlled, and to override the Finalize method.
> > When the sigelton object leaves scope, Finalize than cleans up whatever
> > needs to be cleaned up. At a first look this appeared to work nicely. But
> > when done in a recursive subprogram, Finalize rather unexpectedly seems to
> > always read the local parameters of the innermost scope.
>
> > Here is a test case:
>
> > ---begin fin_test_case.adb
>
> > with Ada.Text_IO, Ada.Finalization;
>
> > procedure Fin_Test_Case is
> >    type Fin is new Ada.Finalization.Limited_Controlled with null record;
>
> >    procedure Do_Something (I: Natural) is
>
> >       type My_Fin is new Fin with null record;
>
> >       overriding procedure Finalize(Self: in out My_Fin) is
> >         S: String := Natural'Image(I);
> >       begin
> >          Ada.Text_IO.Put_Line("  Do_Something Finalization " & S);
> >       end Finalize;
>
> >       Singleton: My_Fin;
>
> >    begin -- Do_Something
> >       Ada.Text_IO.Put_Line("  I = " & Natural'Image(I));
> >       if I>0 then
> >          Do_Something(I-1);
> >          Do_Something(I-1);
> >       end if;
> >    end Do_Something;
>
> > begin
> >    Ada.Text_IO.Put_Line("Start Do_Something (2)");
> >    Do_Something(2);
> >    Ada.Text_IO.Put_Line("Stop Do_Something (2)");
> > end Fin_Test_Case;
>
> > ---end fin_test_case.adb
>
> > This is what I got:
>
> > ---begin output
>
> > Start Do_Something (2)
> >   I =  2
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  0
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  0
> > Stop Do_Something (2)
>
> > ---end output
>
> > Somehow, the local parameter I is always 0 when finalize is called. What I
> > expected was the following:
>
> > ---begin expected output
>
> > Start Do_Something (2)
> >   I =  2
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  1
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  1
> >   Do_Something Finalization  2
> > Stop Do_Something (2)
>
> > ---end expected output
>
> > Now, is my expectation wrong? Or is this a compiler bug? I am using
> > GNAT GPL 2007 (20070405-41).
>
> This looks like a pretty clear compiler bug, especially since by the
> time Finalize is called by the outermost Do_Something, it's using, for
> the value of I, the parameter from a Do_Something call that is no
> longer active.  It shouldn't be hard to modify this slightly, using
> (say) a string or record as a parameter to Do_Something, to create a
> test where utter garbage is displayed; then it would be clearer that
> this is a compiler bug.
>
>                                    -- Adam




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

* Re: unexpected behaviour of finalize
  2008-04-04 16:08 ` Adam Beneschan
  2008-04-04 17:34   ` george.priv
@ 2008-04-04 17:38   ` george.priv
  2008-04-04 17:52     ` stefan-lucks
  2008-04-04 17:51   ` stefan-lucks
  2 siblings, 1 reply; 7+ messages in thread
From: george.priv @ 2008-04-04 17:38 UTC (permalink / raw)


On Apr 4, 12:08 pm, Adam Beneschan <a...@irvine.com> wrote:
> On Apr 4, 2:33 am, stefan-lu...@see.the.signature wrote:
>
>
>
> > Hi,
>
> > I have written a little program to demonstrate finalisation. The idea is
> > to locally declare a singelton object of a class derived from
> > Ada.Finalization.Limited_Controlled, and to override the Finalize method.
> > When the sigelton object leaves scope, Finalize than cleans up whatever
> > needs to be cleaned up. At a first look this appeared to work nicely. But
> > when done in a recursive subprogram, Finalize rather unexpectedly seems to
> > always read the local parameters of the innermost scope.
>
> > Here is a test case:
>
> > ---begin fin_test_case.adb
>
> > with Ada.Text_IO, Ada.Finalization;
>
> > procedure Fin_Test_Case is
> >    type Fin is new Ada.Finalization.Limited_Controlled with null record;
>
> >    procedure Do_Something (I: Natural) is
>
> >       type My_Fin is new Fin with null record;
>
> >       overriding procedure Finalize(Self: in out My_Fin) is
> >         S: String := Natural'Image(I);
> >       begin
> >          Ada.Text_IO.Put_Line("  Do_Something Finalization " & S);
> >       end Finalize;
>
> >       Singleton: My_Fin;
>
> >    begin -- Do_Something
> >       Ada.Text_IO.Put_Line("  I = " & Natural'Image(I));
> >       if I>0 then
> >          Do_Something(I-1);
> >          Do_Something(I-1);
> >       end if;
> >    end Do_Something;
>
> > begin
> >    Ada.Text_IO.Put_Line("Start Do_Something (2)");
> >    Do_Something(2);
> >    Ada.Text_IO.Put_Line("Stop Do_Something (2)");
> > end Fin_Test_Case;
>
> > ---end fin_test_case.adb
>
> > This is what I got:
>
> > ---begin output
>
> > Start Do_Something (2)
> >   I =  2
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  0
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  0
> > Stop Do_Something (2)
>
> > ---end output
>
> > Somehow, the local parameter I is always 0 when finalize is called. What I
> > expected was the following:
>
> > ---begin expected output
>
> > Start Do_Something (2)
> >   I =  2
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  1
> >   I =  1
> >   I =  0
> >   Do_Something Finalization  0
> >   I =  0
> >   Do_Something Finalization  0
> >   Do_Something Finalization  1
> >   Do_Something Finalization  2
> > Stop Do_Something (2)
>
> > ---end expected output
>
> > Now, is my expectation wrong? Or is this a compiler bug? I am using
> > GNAT GPL 2007 (20070405-41).
>
> This looks like a pretty clear compiler bug, especially since by the
> time Finalize is called by the outermost Do_Something, it's using, for
> the value of I, the parameter from a Do_Something call that is no
> longer active.  It shouldn't be hard to modify this slightly, using
> (say) a string or record as a parameter to Do_Something, to create a
> test where utter garbage is displayed; then it would be clearer that
> this is a compiler bug.
>
>                                    -- Adam

With little modification:

procedure Fin_Test_Case is
   type Fin is new Ada.Finalization.Limited_Controlled with null
record;

   procedure Do_Something (I: Natural) is

      type My_Fin(X : natural)  is new Fin with null record;

      overriding procedure Finalize(Self: in out My_Fin) is
         S: String := Natural'Image(I) & ':' & Natural'Image(Self.X);
      begin
         Ada.Text_IO.Put_Line("  Do_Something Finalization " & S);
      end Finalize;

      Singleton: My_Fin(i);

   begin -- Do_Something
      Ada.Text_IO.Put_Line("  I = " & Natural'Image(I));
      if I>0 then
         Do_Something(I-1);
         Do_Something(I-1);
      end if;
   end Do_Something;

begin
   Ada.Text_IO.Put_Line("Start Do_Something (2)");
   Do_Something(2);
   Ada.Text_IO.Put_Line("Stop Do_Something (2)");
end Fin_Test_Case;

The result becomes:

Start Do_Something (2)
  I =  2
  I =  1
  I =  0
  Do_Something Finalization  0: 0
  I =  0
  Do_Something Finalization  0: 0
  Do_Something Finalization  0: 1
  I =  1
  I =  0
  Do_Something Finalization  0: 0
  I =  0
  Do_Something Finalization  0: 0
  Do_Something Finalization  0: 1
  Do_Something Finalization  0: 2
Stop Do_Something (2)

Seems that compiler doing some shortcut with access to wrong I
instance



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

* Re: unexpected behaviour of finalize
  2008-04-04 16:08 ` Adam Beneschan
  2008-04-04 17:34   ` george.priv
  2008-04-04 17:38   ` george.priv
@ 2008-04-04 17:51   ` stefan-lucks
  2 siblings, 0 replies; 7+ messages in thread
From: stefan-lucks @ 2008-04-04 17:51 UTC (permalink / raw)


[-- Attachment #1: Type: TEXT/PLAIN, Size: 2140 bytes --]

> This looks like a pretty clear compiler bug, especially since by the
> time Finalize is called by the outermost Do_Something, it's using, for
> the value of I, the parameter from a Do_Something call that is no
> longer active.  It shouldn't be hard to modify this slightly, using
> (say) a string or record as a parameter to Do_Something, to create a
> test where utter garbage is displayed; then it would be clearer that
> this is a compiler bug.

Good idea! Yes, the following change makes the program output a bit of 
garbage, as you guessed:

procedure Strong_Fin_Test_Case is

   type Fin is new Ada.Finalization.Limited_Controlled with null record;

   procedure Do_Something (I: Natural) is

      A: String(1 .. 5); -- this is new

      type My_Fin is new Fin with null record;
      overriding procedure Finalize(Self: in out My_Fin) is
      begin
         Ada.Text_IO.Put_Line("  Do_Something Finalization " & A);
      end Finalize;
      Singleton: My_Fin;

   begin -- Do_Something
      Ada.Text_IO.Put_Line("  I = " & Natural'Image(I));
      if I>0 then
         Do_Something(I-1);
         Do_Something(I-1);
      end if;
      A(1 .. 5) := ("ABCDE"); -- always the same
   end Do_Something;

begin
   Ada.Text_IO.Put_Line("Start Do_Something (2)");
   Do_Something(2);
   Ada.Text_IO.Put_Line("Stop Do_Something (2)");
end Strong_Fin_Test_Case;


The putput:


Start Do_Something (2)
  I =  2
  I =  1
  I =  0
  Do_Something Finalization ABCDE
  I =  0
  Do_Something Finalization ABCDE
  Do_Something Finalization ABCDE
  I =  1
  I =  0
  Do_Something Finalization ABCDE
  I =  0
  Do_Something Finalization ABCDE
  Do_Something Finalization ABCDE
  Do_Something Finalization �l
Stop Do_Something (2)

The last line before "Stop Do_Something (2)" contains some strange 
characters instead of the constant "ABCDE" it should output. Furthermore, 
this output is not always the same. 

So long

Stefan



-- 
------ Stefan Lucks   --  Bauhaus-University Weimar  --   Germany  ------
               Stefan dot Lucks at uni minus weimar dot de
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------

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

* Re: unexpected behaviour of finalize
  2008-04-04 17:38   ` george.priv
@ 2008-04-04 17:52     ` stefan-lucks
  2008-04-04 19:53       ` george.priv
  0 siblings, 1 reply; 7+ messages in thread
From: stefan-lucks @ 2008-04-04 17:52 UTC (permalink / raw)


> Seems that compiler doing some shortcut with access to wrong I
> instance


Indeed! 

Are you using the same compiler (GNAT GPL 2007 (20070405-41))?

Stefan

-- 
------ Stefan Lucks   --  Bauhaus-University Weimar  --   Germany  ------
               Stefan dot Lucks at uni minus weimar dot de
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------




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

* Re: unexpected behaviour of finalize
  2008-04-04 17:52     ` stefan-lucks
@ 2008-04-04 19:53       ` george.priv
  0 siblings, 0 replies; 7+ messages in thread
From: george.priv @ 2008-04-04 19:53 UTC (permalink / raw)


On Apr 4, 1:52 pm, stefan-lu...@see-the.signature wrote:
> > Seems that compiler doing some shortcut with access to wrong I
> > instance
>
> Indeed!
>
> Are you using the same compiler (GNAT GPL 2007 (20070405-41))?
>
> Stefan
>
> --
> ------ Stefan Lucks   --  Bauhaus-University Weimar  --   Germany  ------
>                Stefan dot Lucks at uni minus weimar dot de
> ------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------

Yes



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

end of thread, other threads:[~2008-04-04 19:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-04  9:33 unexpected behaviour of finalize stefan-lucks
2008-04-04 16:08 ` Adam Beneschan
2008-04-04 17:34   ` george.priv
2008-04-04 17:38   ` george.priv
2008-04-04 17:52     ` stefan-lucks
2008-04-04 19:53       ` george.priv
2008-04-04 17:51   ` stefan-lucks

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