comp.lang.ada
 help / color / mirror / Atom feed
* Error: allocation from empty storage pool
@ 2018-07-12  9:50 Alejandro R. Mosteo
  2018-07-12 11:41 ` Simon Wright
  0 siblings, 1 reply; 5+ messages in thread
From: Alejandro R. Mosteo @ 2018-07-12  9:50 UTC (permalink / raw)


In a library I'm trying to have all allocations done from user-specified 
storage pools. There is no restriction on using the heap, as long as it 
comes from a user pool (that can default to the regular heap, of course).

The idea was then to use "pragma Default_Storage_Pool (null)" at the 
library root to ensure no use of default allocators, and wherever needed 
provide facilities to get a pool from the user.

However, this test fails:

---8<---

pragma Restrictions (No_Secondary_Stack); -- Just to be sure in this ex.
pragma Default_Storage_Pool (null);

procedure Anon is

    type Holder is record
       I : aliased Integer;
    end record;

    type Ref (Elem : access constant Integer) is limited null record;

    function To_Ref (Hold : aliased Holder) return Ref is
      (Elem => Hold.I'Access); -- Error in subject here

begin
    null;
end Anon;

---8<---

There's actually no allocation being made, and I could have a Holder 
variable in the stack, and take a reference, and still no pool would be 
used at all.

So it seems this pragma is too naïve. To make it into questions:

Is this the pragma expected behavior or a particularity of gnat? Is the 
approach reasonable? This is my first attempt at working in a 
"restricted" Ada environment so I don't really have a clear idea of the 
preferred way to do what I want. Also, I'd like if possible to avoid 
making everything generic on the user pool.

Thanks,
Álex.


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

* Re: Error: allocation from empty storage pool
  2018-07-12  9:50 Error: allocation from empty storage pool Alejandro R. Mosteo
@ 2018-07-12 11:41 ` Simon Wright
  2018-07-12 12:14   ` Alejandro R. Mosteo
  0 siblings, 1 reply; 5+ messages in thread
From: Simon Wright @ 2018-07-12 11:41 UTC (permalink / raw)


"Alejandro R. Mosteo" <alejandro@mosteo.com> writes:

> In a library I'm trying to have all allocations done from
> user-specified storage pools. There is no restriction on using the
> heap, as long as it comes from a user pool (that can default to the
> regular heap, of course).
>
> The idea was then to use "pragma Default_Storage_Pool (null)" at the
> library root to ensure no use of default allocators, and wherever
> needed provide facilities to get a pool from the user.
>
> However, this test fails:
>
> ---8<---
>
> pragma Restrictions (No_Secondary_Stack); -- Just to be sure in this ex.
> pragma Default_Storage_Pool (null);
>
> procedure Anon is
>
>    type Holder is record
>       I : aliased Integer;
>    end record;
>
>    type Ref (Elem : access constant Integer) is limited null record;
>
>    function To_Ref (Hold : aliased Holder) return Ref is
>      (Elem => Hold.I'Access); -- Error in subject here
>
> begin
>    null;
> end Anon;
>
> ---8<---
>
> There's actually no allocation being made, and I could have a Holder
> variable in the stack, and take a reference, and still no pool would
> be used at all.
>
> So it seems this pragma is too naïve. To make it into questions:
>
> Is this the pragma expected behavior or a particularity of gnat? Is
> the approach reasonable? This is my first attempt at working in a
> "restricted" Ada environment so I don't really have a clear idea of
> the preferred way to do what I want. Also, I'd like if possible to
> avoid making everything generic on the user pool.

I'm 99% confident this is a bug in GNAT.

The repreentation of the generated code (-gnatG) for To_Ref is

   function to_ref (hold : aliased holder; to_refBIPalloc : natural;
     to_refBIPstoragepool :
     system__storage_pools__root_storage_pool_ptr; to_refBIPaccess :
     T5b) return ref is
   begin
      R14b : declare
         [subtype T12b is ref (hold.i'access)]
         type A16b is access all T12b;
         R17b : A16b := null;
         if to_refBIPalloc = 1 then
            R17b := A16b!(to_refBIPaccess);
         elsif to_refBIPalloc = 2 then
            R17b := new T12b[storage_pool =
              system__secondary_stack__ss_pool];
         elsif to_refBIPalloc = 3 then
            R17b := new T12b;
         elsif to_refBIPalloc = 4 then
            P15b : system__storage_pools__root_storage_pool renames
              to_refBIPstoragepool.all;
            R17b := new T12b[storage_pool = P15b];
         else
            [program_error "build in place mismatch"]
         end if;
         R13b : T12b renames R17b.all;
         R13b.elem := hold.i'access;
      begin
         return R13b;
      end R14b;
   end to_ref;

where to_refBIPalloc is a parameter determined by the compiler. In the
case of

   H : aliased Holder := (I => 42);
   R : Ref := To_Ref (H);

it's 1, and to_refBIPaccess is R'Unrestricted_Access.

The other cases are presumably to cope with other calling patterns
(can't imagine what), and in particular case 3 is a standard 'new',
which would be what triggers the error message.


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

* Re: Error: allocation from empty storage pool
  2018-07-12 11:41 ` Simon Wright
@ 2018-07-12 12:14   ` Alejandro R. Mosteo
  2018-07-12 21:08     ` Randy Brukardt
  0 siblings, 1 reply; 5+ messages in thread
From: Alejandro R. Mosteo @ 2018-07-12 12:14 UTC (permalink / raw)


On 12/07/2018 13:41, Simon Wright wrote:
> "Alejandro R. Mosteo" <alejandro@mosteo.com> writes:
> 
>> In a library I'm trying to have all allocations done from
>> user-specified storage pools. There is no restriction on using the
>> heap, as long as it comes from a user pool (that can default to the
>> regular heap, of course).
>>
>> The idea was then to use "pragma Default_Storage_Pool (null)" at the
>> library root to ensure no use of default allocators, and wherever
>> needed provide facilities to get a pool from the user.
>>
>> However, this test fails:
>>
>> ---8<---
>>
>> pragma Restrictions (No_Secondary_Stack); -- Just to be sure in this ex.
>> pragma Default_Storage_Pool (null);
>>
>> procedure Anon is
>>
>>     type Holder is record
>>        I : aliased Integer;
>>     end record;
>>
>>     type Ref (Elem : access constant Integer) is limited null record;
>>
>>     function To_Ref (Hold : aliased Holder) return Ref is
>>       (Elem => Hold.I'Access); -- Error in subject here
>>
>> begin
>>     null;
>> end Anon;
>>
>> ---8<---
>>
>> There's actually no allocation being made, and I could have a Holder
>> variable in the stack, and take a reference, and still no pool would
>> be used at all.
>>
>> So it seems this pragma is too naïve. To make it into questions:
>>
>> Is this the pragma expected behavior or a particularity of gnat? Is
>> the approach reasonable? This is my first attempt at working in a
>> "restricted" Ada environment so I don't really have a clear idea of
>> the preferred way to do what I want. Also, I'd like if possible to
>> avoid making everything generic on the user pool.
> 
> I'm 99% confident this is a bug in GNAT.

Thanks for the analysis, that's a neat way of seeing what's going on. I 
guess I will report it then.

I was thinking that maybe the pragma works at the access type level 
instead of actual allocations. That is, any access type without 
'Storage_size => 0 or explicit allocator would fail. But reading 13.11.3 
6/3 it seems that it is the other way around: at the point of the access 
type declaration either default 'Storage_Size or 'Storage_Pool is 
determined depending on the Default_Storage_Pool value. Though I am not a 
l-lawyer so...

Álex.

> 
> The repreentation of the generated code (-gnatG) for To_Ref is
> 
>     function to_ref (hold : aliased holder; to_refBIPalloc : natural;
>       to_refBIPstoragepool :
>       system__storage_pools__root_storage_pool_ptr; to_refBIPaccess :
>       T5b) return ref is
>     begin
>        R14b : declare
>           [subtype T12b is ref (hold.i'access)]
>           type A16b is access all T12b;
>           R17b : A16b := null;
>           if to_refBIPalloc = 1 then
>              R17b := A16b!(to_refBIPaccess);
>           elsif to_refBIPalloc = 2 then
>              R17b := new T12b[storage_pool =
>                system__secondary_stack__ss_pool];
>           elsif to_refBIPalloc = 3 then
>              R17b := new T12b;
>           elsif to_refBIPalloc = 4 then
>              P15b : system__storage_pools__root_storage_pool renames
>                to_refBIPstoragepool.all;
>              R17b := new T12b[storage_pool = P15b];
>           else
>              [program_error "build in place mismatch"]
>           end if;
>           R13b : T12b renames R17b.all;
>           R13b.elem := hold.i'access;
>        begin
>           return R13b;
>        end R14b;
>     end to_ref;
> 
> where to_refBIPalloc is a parameter determined by the compiler. In the
> case of
> 
>     H : aliased Holder := (I => 42);
>     R : Ref := To_Ref (H);
> 
> it's 1, and to_refBIPaccess is R'Unrestricted_Access.
> 
> The other cases are presumably to cope with other calling patterns
> (can't imagine what), and in particular case 3 is a standard 'new',
> which would be what triggers the error message.
> 


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

* Re: Error: allocation from empty storage pool
  2018-07-12 12:14   ` Alejandro R. Mosteo
@ 2018-07-12 21:08     ` Randy Brukardt
  2018-07-13  8:02       ` Alejandro R. Mosteo
  0 siblings, 1 reply; 5+ messages in thread
From: Randy Brukardt @ 2018-07-12 21:08 UTC (permalink / raw)


"Alejandro R. Mosteo" <alejandro@mosteo.com> wrote in message 
news:pi7gmk$riu$1@dont-email.me...
...
> I was thinking that maybe the pragma works at the access type level 
> instead of actual allocations. That is, any access type without 
> 'Storage_size => 0 or explicit allocator would fail. But reading 13.11.3 
> 6/3 it seems that it is the other way around: at the point of the access 
> type declaration either default 'Storage_Size or 'Storage_Pool is 
> determined depending on the Default_Storage_Pool value. Though I am not a 
> l-lawyer so...

Correct. But note that when Default_Storage_Pool is null, then Storage_Size 
=> 0. When Storage_Size is statically zero, allocators are illegal 
(4.8(5.4/3)), as are calls on instances of Unchecked_Deallocation 
(13.11.2(3.1/3)). It's allowed to declare such types, so that one can use 
'Access to give them values.

I don't see any language reason for an allocator to be used in your example, 
so I concur that there is a GNAT bug involved.

                                          Randy.


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

* Re: Error: allocation from empty storage pool
  2018-07-12 21:08     ` Randy Brukardt
@ 2018-07-13  8:02       ` Alejandro R. Mosteo
  0 siblings, 0 replies; 5+ messages in thread
From: Alejandro R. Mosteo @ 2018-07-13  8:02 UTC (permalink / raw)


On 12/07/2018 23:08, Randy Brukardt wrote:
> "Alejandro R. Mosteo" <alejandro@mosteo.com> wrote in message
> news:pi7gmk$riu$1@dont-email.me...
> ...
>> I was thinking that maybe the pragma works at the access type level
>> instead of actual allocations. That is, any access type without
>> 'Storage_size => 0 or explicit allocator would fail. But reading 13.11.3
>> 6/3 it seems that it is the other way around: at the point of the access
>> type declaration either default 'Storage_Size or 'Storage_Pool is
>> determined depending on the Default_Storage_Pool value. Though I am not a
>> l-lawyer so...
> 
> Correct. But note that when Default_Storage_Pool is null, then Storage_Size
> => 0. When Storage_Size is statically zero, allocators are illegal
> (4.8(5.4/3)), as are calls on instances of Unchecked_Deallocation
> (13.11.2(3.1/3)). It's allowed to declare such types, so that one can use
> 'Access to give them values.
> 
> I don't see any language reason for an allocator to be used in your example,
> so I concur that there is a GNAT bug involved.

I reported it yesterday and I just got confirmation that it is a bug.

Thanks,
Álex.

> 
>                                            Randy.
> 
> 

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

end of thread, other threads:[~2018-07-13  8:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-12  9:50 Error: allocation from empty storage pool Alejandro R. Mosteo
2018-07-12 11:41 ` Simon Wright
2018-07-12 12:14   ` Alejandro R. Mosteo
2018-07-12 21:08     ` Randy Brukardt
2018-07-13  8:02       ` Alejandro R. Mosteo

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