comp.lang.ada
 help / color / mirror / Atom feed
* Limited type in generic package causes double free or corruption
@ 2016-09-28 13:25 onox
  2016-09-28 16:06 ` Dmitry A. Kazakov
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: onox @ 2016-09-28 13:25 UTC (permalink / raw)


I have a generic package (A) with a limited type (Tree). The generic package is used as a generic formal parameter in another generic package (B). This second generic package has a primitive operation (Get_Tree) that returns a component of a tagged record that is of that limited type. Calling that primitive operation results in a "double free or corruption (fasttop)" message when the program terminates.

Shouldn't the compiler (GNAT GPL 2015) check that the type in the generic formal parameter (package) is limited and forbid the copying operation? If I remove the "limited" keyword from the type, then the program terminates without any errors.

Compile via gnatmake c.adb

I put the example in a separate task, otherwise the program could just hang with 100 % CPU instead of displaying the error and terminating.

onox

--  File a.ads
private with Ada.Containers.Vectors;

generic
   Foo : Positive;
package A is

   --  Remove "limited" keyword to avoid double-free or corruption
   type Tree is tagged limited private;

   function Create_Tree return Tree;

private

   package Level_Vectors is new Ada.Containers.Vectors (Positive, Positive);

   --  Remove "limited" keyword to avoid double-free or corruption
   type Tree is tagged limited record
      Levels : Level_Vectors.Vector;
   end record;

end A;
--  End of file a.ads

--  File a.adb
package body A is

   function Create_Tree return Tree is
   begin
      return Object : Tree do
         Object.Levels.Append (10);
      end return;
   end Create_Tree;

end A;
--  End of file a.adb

--  File b.ads
with A;

generic
   with package Trees is new A (<>);
package B is

   type Thing is tagged limited private;

   function Load_Thing return Thing;

   function Get_Tree (Object : Thing) return Trees.Tree;

private

   type Thing is tagged limited record
      My_Tree : Trees.Tree;
   end record;

end B;
--  End of file b.ads

--  File b.adb
package body B is

   function Load_Thing return Thing is
   begin
      return Object : Thing := (My_Tree => Trees.Create_Tree) do
         null;
      end return;
   end Load_Thing;

   --  If Trees.Tree (A.Tree) is limited, shouldn't this function be disallowed?
   function Get_Tree (Object : Thing) return Trees.Tree is
     (Object.My_Tree);

end B;
--  End of file b.adb

--  File c.adb
with Ada.Text_IO;
with A;
with B;

procedure C is

   task Worker;

   task body Worker is
      package AA is new A (1);
      use AA;
      package Things is new B (AA);

      M : Things.Thing := Things.Load_Thing;
      T : Tree := M.Get_Tree;
   begin
      Ada.Text_IO.Put_Line ("Worker thread");
   end Worker;

begin
   Ada.Text_IO.Put_Line ("Environment thread");
end C;
--  End of file c.adb


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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 13:25 Limited type in generic package causes double free or corruption onox
@ 2016-09-28 16:06 ` Dmitry A. Kazakov
  2016-09-28 16:20 ` Jeffrey R. Carter
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2016-09-28 16:06 UTC (permalink / raw)


On 2016-09-28 15:25, onox wrote:

> Shouldn't the compiler (GNAT GPL 2015) check that the type in the
> generic formal parameter (package) is limited and forbid the copying
> operation?

No, limited return kludge (bug IMO) was introduced to Ada.

> If I remove the "limited" keyword from the type, then the
> program terminates without any errors.

Limited return does not work well (and has no sense anyway).

And you must decide about the semantics of "returning" a tree. It can be 
deep copy or shallow copy. In the latter case there should be a node 
reference counting schema deployed to clone updated nodes visible 
through several references. Either would prevent "corruption".

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


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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 13:25 Limited type in generic package causes double free or corruption onox
  2016-09-28 16:06 ` Dmitry A. Kazakov
@ 2016-09-28 16:20 ` Jeffrey R. Carter
  2016-09-28 18:41   ` onox
  2016-09-28 17:27 ` Anh Vo
  2016-09-28 17:34 ` AdaMagica
  3 siblings, 1 reply; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-09-28 16:20 UTC (permalink / raw)


On 09/28/2016 06:25 AM, onox wrote:
> 
>    --  If Trees.Tree (A.Tree) is limited, shouldn't this function be disallowed?
>    function Get_Tree (Object : Thing) return Trees.Tree is
>      (Object.My_Tree);

What do you get if you rewrite this function as

function Get_Tree (Object : Thing) return Trees.Tree is
begin
   return Object.My_Tree;
end Get_Tree;

? The two forms should be equivalent.

-- 
Jeff Carter
"Death awaits you all, with nasty, big, pointy teeth!"
Monty Python & the Holy Grail
20


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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 13:25 Limited type in generic package causes double free or corruption onox
  2016-09-28 16:06 ` Dmitry A. Kazakov
  2016-09-28 16:20 ` Jeffrey R. Carter
@ 2016-09-28 17:27 ` Anh Vo
  2016-09-28 17:34 ` AdaMagica
  3 siblings, 0 replies; 9+ messages in thread
From: Anh Vo @ 2016-09-28 17:27 UTC (permalink / raw)


On Wednesday, September 28, 2016 at 6:26:02 AM UTC-7, onox wrote:
> I have a generic package (A) with a limited type (Tree). The generic package is used as a generic formal parameter in another generic package (B). This second generic package has a primitive operation (Get_Tree) that returns a component of a tagged record that is of that limited type. Calling that primitive operation results in a "double free or corruption (fasttop)" message when the program terminates.
> 
> Shouldn't the compiler (GNAT GPL 2015) check that the type in the generic formal parameter (package) is limited and forbid the copying operation? If I remove the "limited" keyword from the type, then the program terminates without any errors.
> 
> Compile via gnatmake c.adb
> 
> I put the example in a separate task, otherwise the program could just hang with 100 % CPU instead of displaying the error and terminating.
> 
> onox
> 
> --  File a.ads
> private with Ada.Containers.Vectors;
> 
> generic
>    Foo : Positive;
> package A is
> 
>    --  Remove "limited" keyword to avoid double-free or corruption
>    type Tree is tagged limited private;
> 
>    function Create_Tree return Tree;
> 
> private
> 
>    package Level_Vectors is new Ada.Containers.Vectors (Positive, Positive);
> 
>    --  Remove "limited" keyword to avoid double-free or corruption
>    type Tree is tagged limited record
>       Levels : Level_Vectors.Vector;
>    end record;
> 
> end A;
> --  End of file a.ads
> 
> --  File a.adb
> package body A is
> 
>    function Create_Tree return Tree is
>    begin
>       return Object : Tree do
>          Object.Levels.Append (10);
>       end return;
>    end Create_Tree;
> 
> end A;
> --  End of file a.adb
> 
> --  File b.ads
> with A;
> 
> generic
>    with package Trees is new A (<>);
> package B is
> 
>    type Thing is tagged limited private;
> 
>    function Load_Thing return Thing;
> 
>    function Get_Tree (Object : Thing) return Trees.Tree;
> 
> private
> 
>    type Thing is tagged limited record
>       My_Tree : Trees.Tree;
>    end record;
> 
> end B;
> --  End of file b.ads
> 
> --  File b.adb
> package body B is
> 
>    function Load_Thing return Thing is
>    begin
>       return Object : Thing := (My_Tree => Trees.Create_Tree) do
>          null;
>       end return;
>    end Load_Thing;
> 
>    --  If Trees.Tree (A.Tree) is limited, shouldn't this function be disallowed?
>    function Get_Tree (Object : Thing) return Trees.Tree is
>      (Object.My_Tree);
> 
> end B;
> --  End of file b.adb
> 
> --  File c.adb
> with Ada.Text_IO;
> with A;
> with B;
> 
> procedure C is
> 
>    task Worker;
> 
>    task body Worker is
>       package AA is new A (1);
>       use AA;
>       package Things is new B (AA);
> 
>       M : Things.Thing := Things.Load_Thing;
>       T : Tree := M.Get_Tree;
>    begin
>       Ada.Text_IO.Put_Line ("Worker thread");
>    end Worker;
> 
> begin
>    Ada.Text_IO.Put_Line ("Environment thread");
> end C;
> --  End of file c.adb

Your codes work fine under GNAT GPL 2016. Of course, you need to pass compiler flag -gnat2012 during compilation.

Anh Vo

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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 13:25 Limited type in generic package causes double free or corruption onox
                   ` (2 preceding siblings ...)
  2016-09-28 17:27 ` Anh Vo
@ 2016-09-28 17:34 ` AdaMagica
  2016-09-28 21:42   ` Randy Brukardt
  3 siblings, 1 reply; 9+ messages in thread
From: AdaMagica @ 2016-09-28 17:34 UTC (permalink / raw)


Am Mittwoch, 28. September 2016 15:26:02 UTC+2 schrieb onox:
>    function Load_Thing return Thing is
>    begin
>       return Object : Thing := (My_Tree => Trees.Create_Tree) do
>          null;
>       end return;
>    end Load_Thing;
You can return *new* limited objects - they are created in-place.

>    --  If Trees.Tree (A.Tree) is limited, shouldn't this function be disallowed?
>    function Get_Tree (Object : Thing) return Trees.Tree is
>      (Object.My_Tree);
Correct, this should not compile - you cannot return existing limited objects.

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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 16:20 ` Jeffrey R. Carter
@ 2016-09-28 18:41   ` onox
  2016-09-28 19:51     ` Jeffrey R. Carter
  2016-09-29  8:12     ` Alejandro R. Mosteo
  0 siblings, 2 replies; 9+ messages in thread
From: onox @ 2016-09-28 18:41 UTC (permalink / raw)


On Wednesday, September 28, 2016 at 6:20:27 PM UTC+2, Jeffrey R. Carter wrote:
> What do you get if you rewrite this function as
> 
> function Get_Tree (Object : Thing) return Trees.Tree is
> begin
>    return Object.My_Tree;
> end Get_Tree;
> 
> ? The two forms should be equivalent.

Then I get (with -gnat2012) this:

>>> (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2))
>>> return by reference not permitted in Ada 2005

The error seems to refer to a paragraph in the RM that has been deleted in RM-2012. See http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-6-5.html item 5.6/3 and 5.c/3.

5.6/3 refers to section 7.5 (http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-7-5.html). If I understand 2.9/3 in section 7.5 correctly, my current code should be allowed (which may explain why it does compile in GNAT 2016 according to Anh Vo).

Anyway, Get_Tree is simply meant as a getter. In my non-example code, the tree is constructed in the extended return in Load_Thing.

If Tree is tagged (which it is), doesn't that mean Ada uses copy-by-reference instead of copy-by-value. Or am I mixing things up here?

If it doesn't, then the Tree record is simply copied, and because Ada.Containers.Vectors is controlled, it's basically just a shallow copy?


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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 18:41   ` onox
@ 2016-09-28 19:51     ` Jeffrey R. Carter
  2016-09-29  8:12     ` Alejandro R. Mosteo
  1 sibling, 0 replies; 9+ messages in thread
From: Jeffrey R. Carter @ 2016-09-28 19:51 UTC (permalink / raw)


On 09/28/2016 11:41 AM, onox wrote:
> 
> Then I get (with -gnat2012) this:
> 
>>>> (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2))
>>>> return by reference not permitted in Ada 2005
> 
> The error seems to refer to a paragraph in the RM that has been deleted in RM-2012. See
http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-6-5.html
item 5.6/3 and 5.c/3.

I expected an error, though this is not a very useful message. The referenced
paragraph in the ARM for ISO/IEC 8652:2007 reads, "If the result subtype of the
function is limited, then the expression of the return statement (if any) shall
be an aggregate, a function call (or equivalent use of an operator), or a
qualified_expression or parenthesized expression whose operand is one of these."

> 5.6/3 refers to section 7.5
(http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-7-5.html).
If I understand 2.9/3 in section 7.5 correctly, my current code should be
allowed (which may explain why it does compile in GNAT 2016 according to Anh Vo).

No, 2.9 says that the expression of an expression function that returns a
limited type must be something allowed by 2.1: basically an aggregate or
function call. Your expression function's expression is an object, which is not
allowed. I think you have discovered a GNAT error in compiling expression
functions that return a limited type.

> If Tree is tagged (which it is), doesn't that mean Ada uses
> copy-by-reference
instead of copy-by-value. Or am I mixing things up here?

You are confused, though I'm not sure about what. Since Tree is limited, it
cannot be copied.

-- 
Jeff Carter
"Brave Sir Robin ran away."
Monty Python and the Holy Grail
59


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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 17:34 ` AdaMagica
@ 2016-09-28 21:42   ` Randy Brukardt
  0 siblings, 0 replies; 9+ messages in thread
From: Randy Brukardt @ 2016-09-28 21:42 UTC (permalink / raw)


"AdaMagica" <christ-usch.grein@t-online.de> wrote in message 
news:c6cae5e7-a215-4560-aa8a-d15ce4bd0852@googlegroups.com...
> Am Mittwoch, 28. September 2016 15:26:02 UTC+2 schrieb onox:
>>    function Load_Thing return Thing is
>>    begin
>>       return Object : Thing := (My_Tree => Trees.Create_Tree) do
>>          null;
>>       end return;
>>    end Load_Thing;
> You can return *new* limited objects - they are created in-place.
>
>>    --  If Trees.Tree (A.Tree) is limited, shouldn't this function be 
>> disallowed?
>>    function Get_Tree (Object : Thing) return Trees.Tree is
>>      (Object.My_Tree);
> Correct, this should not compile - you cannot return existing limited 
> objects.

And if the compiler is allowing it, it is wrong. Report a bug to the vendor.

                                Randy.



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

* Re: Limited type in generic package causes double free or corruption
  2016-09-28 18:41   ` onox
  2016-09-28 19:51     ` Jeffrey R. Carter
@ 2016-09-29  8:12     ` Alejandro R. Mosteo
  1 sibling, 0 replies; 9+ messages in thread
From: Alejandro R. Mosteo @ 2016-09-29  8:12 UTC (permalink / raw)


On 28/09/16 20:41, onox wrote:

> If Tree is tagged (which it is), doesn't that mean Ada uses copy-by-reference instead of copy-by-value. Or am I mixing things up here?

Copy is never by reference in Ada (other than when explicitly using 
access types, of course). You're perhaps thinking of the 
parameter-passing mechanism? That's indeed by reference for tagged types 
(although for the programmer the allowed operations are as per the 
in/out mode as usual).

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

end of thread, other threads:[~2016-09-29  8:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-28 13:25 Limited type in generic package causes double free or corruption onox
2016-09-28 16:06 ` Dmitry A. Kazakov
2016-09-28 16:20 ` Jeffrey R. Carter
2016-09-28 18:41   ` onox
2016-09-28 19:51     ` Jeffrey R. Carter
2016-09-29  8:12     ` Alejandro R. Mosteo
2016-09-28 17:27 ` Anh Vo
2016-09-28 17:34 ` AdaMagica
2016-09-28 21:42   ` Randy Brukardt

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