* 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 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
* 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