comp.lang.ada
 help / color / mirror / Atom feed
* Pitfall: freeing access discriminants
@ 2003-02-13 10:04 Victor Porton
  2003-02-13 12:07 ` Victor Porton
  2003-02-13 17:40 ` Stephen Leake
  0 siblings, 2 replies; 15+ messages in thread
From: Victor Porton @ 2003-02-13 10:04 UTC (permalink / raw)


type Integer_Access is access Integer;

type T(D: access Integer) is Ada.Limited_Controlled with null record;

procedure Finalize(Object: in out T) is
  -- Error: cannot convert access discriminant to non-local access type
  D: Integer_Access := Integer_Access(Object.D);
begin
  Free(D);
end;

What to do? It seems being a serious deficiency in Ada or there are a 
workaround?



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 10:04 Victor Porton
@ 2003-02-13 12:07 ` Victor Porton
  2003-02-13 13:42   ` Preben Randhol
  2003-02-13 17:40 ` Stephen Leake
  1 sibling, 1 reply; 15+ messages in thread
From: Victor Porton @ 2003-02-13 12:07 UTC (permalink / raw)


In article <E18jGE0-0003dI-00@porton.narod.ru>,
	porton@ex-code.com (Victor Porton) writes:
> type Integer_Access is access Integer;
> 
> type T(D: access Integer) is Ada.Limited_Controlled with null record;
> 
> procedure Finalize(Object: in out T) is
>   -- Error: cannot convert access discriminant to non-local access type
>   D: Integer_Access := Integer_Access(Object.D);
> begin
>   Free(D);
> end;
> 
> What to do? It seems being a serious deficiency in Ada or there are a 
> workaround?

I found a solution myself:

Base: Base_Element_Access := Object.Base.all'Unchecked_Access;



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

* Re: Pitfall: freeing access discriminants
@ 2003-02-13 12:41 Grein, Christoph
  2003-02-13 13:38 ` Victor Porton
  0 siblings, 1 reply; 15+ messages in thread
From: Grein, Christoph @ 2003-02-13 12:41 UTC (permalink / raw)
  To: comp.lang.ada

This works, but you have to be careful with the allocation pools.
Also access discriminants can never be null, so if you deallocate the object it 
is accessing, ...

Ok, here you are safe since you finalize the whole object.

with Ada.Finalization;

package Acc_Dis is

  type T (D: access Integer) is
    new Ada.Finalization.Limited_Controlled with null record;

  procedure Finalize (Object: in out T);

  V: T (new Integer'(5));

end Acc_Dis;
with Ada.Unchecked_Deallocation;

package body Acc_Dis is

  procedure Finalize (Object: in out T) is
    type Integer_Ptr is access all Integer;
    procedure Free is new Ada.Unchecked_Deallocation (Integer, Integer_Ptr);
    P: Integer_Ptr := Integer_Ptr (Object.D);
  begin
    Free (P);
  end Finalize;

end Acc_Dis;
-----------------------
Also this works:

with Ada.Finalization;

package Acc_Dis is

  type Integer_Ptr is access Integer;

  type T (D: Integer_Ptr) is
    new Ada.Finalization.[Limited_]Controlled with null record;
  -- An access subtype discriminate does not afford a limited type.

  procedure Finalize (Object: in out T);

  V: T (new Integer'(5));

end Acc_Dis;
with Ada.Unchecked_Deallocation;

package body Acc_Dis is

  procedure Free is new Ada.Unchecked_Deallocation (Integer, Integer_Ptr);

  procedure Finalize (Object: in out T) is
    P: Integer_Ptr := Object.D;
  begin
    Free (P);
  end Finalize;

end Acc_Dis;



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 12:41 Pitfall: freeing access discriminants Grein, Christoph
@ 2003-02-13 13:38 ` Victor Porton
  2003-02-13 20:49   ` tmoran
  0 siblings, 1 reply; 15+ messages in thread
From: Victor Porton @ 2003-02-13 13:38 UTC (permalink / raw)


In article <mailman.4.1045140569.13246.comp.lang.ada@ada.eu.org>,
	"Grein, Christoph" <christoph.grein@eurocopter.com> writes:
> This works, but you have to be careful with the allocation pools.
> Also access discriminants can never be null, so if you deallocate the object it 
> is accessing, ...
> 
> Ok, here you are safe since you finalize the whole object.
> 
> with Ada.Finalization;
> 
> package Acc_Dis is
> 
>   type T (D: access Integer) is
>     new Ada.Finalization.Limited_Controlled with null record;
> 
>   procedure Finalize (Object: in out T);
> 
>   V: T (new Integer'(5));
> 
> end Acc_Dis;
> with Ada.Unchecked_Deallocation;
> 
> package body Acc_Dis is
> 
>   procedure Finalize (Object: in out T) is
>     type Integer_Ptr is access all Integer;
>     procedure Free is new Ada.Unchecked_Deallocation (Integer, Integer_Ptr);
>     P: Integer_Ptr := Integer_Ptr (Object.D);
>   begin
>     Free (P);
>   end Finalize;
> 
> end Acc_Dis;

Oops, I've found that this in not safe and even may lead to erraneous 
execution!! Because of storage pools for Integer_Ptr may be different 
from storage pool used by "new".



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 12:07 ` Victor Porton
@ 2003-02-13 13:42   ` Preben Randhol
  0 siblings, 0 replies; 15+ messages in thread
From: Preben Randhol @ 2003-02-13 13:42 UTC (permalink / raw)


Victor Porton wrote:
> 
> I found a solution myself:
> 
> Base: Base_Element_Access := Object.Base.all'Unchecked_Access;

Not a safe solution. Follow Chris' advice instead.

-- 
Preben Randhol ---------------- http://www.pvv.org/~randhol/ --
"Violence is the last refuge of the incompetent", Isaac Asimov



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 10:04 Victor Porton
  2003-02-13 12:07 ` Victor Porton
@ 2003-02-13 17:40 ` Stephen Leake
  2003-02-13 19:24   ` Victor Porton
  1 sibling, 1 reply; 15+ messages in thread
From: Stephen Leake @ 2003-02-13 17:40 UTC (permalink / raw)


porton@ex-code.com (Victor Porton) writes:

> type Integer_Access is access Integer;
> 
> type T(D: access Integer) is Ada.Limited_Controlled with null record;
> 
> procedure Finalize(Object: in out T) is
>   -- Error: cannot convert access discriminant to non-local access type
>   D: Integer_Access := Integer_Access(Object.D);
> begin
>   Free(D);
> end;
> 
> What to do? It seems being a serious deficiency in Ada or there are a 
> workaround?

Why would you ever want to free an access discriminant? I usually use
them to point to a constant object.

One good rule for dynamic memory allocation; never free something you
did not allocate.

-- 
-- Stephe



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 17:40 ` Stephen Leake
@ 2003-02-13 19:24   ` Victor Porton
  0 siblings, 0 replies; 15+ messages in thread
From: Victor Porton @ 2003-02-13 19:24 UTC (permalink / raw)


In article <uptpwoz8r.fsf@nasa.gov>,
	Stephen Leake <Stephen.A.Leake@nasa.gov> writes:
> porton@ex-code.com (Victor Porton) writes:
> 
>> type Integer_Access is access Integer;
>> 
>> type T(D: access Integer) is Ada.Limited_Controlled with null record;
>> 
>> procedure Finalize(Object: in out T) is
>>   -- Error: cannot convert access discriminant to non-local access type
>>   D: Integer_Access := Integer_Access(Object.D);
>> begin
>>   Free(D);
>> end;
>> 
>> What to do? It seems being a serious deficiency in Ada or there are a 
>> workaround?
> 
> Why would you ever want to free an access discriminant? I usually use
> them to point to a constant object.
> 
> One good rule for dynamic memory allocation; never free something you
> did not allocate.

Just

X: T(new Integer'(12)); -- The real example is more natural
  -- than allocating an integer.

However I realized that Ada access discriminants are not to be used in 
such the way as this causes a great non-reliability. I switched to 
just record memebers of an access type.



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 13:38 ` Victor Porton
@ 2003-02-13 20:49   ` tmoran
  2003-02-13 21:17     ` Simon Wright
  2003-02-14  8:28     ` Victor Porton
  0 siblings, 2 replies; 15+ messages in thread
From: tmoran @ 2003-02-13 20:49 UTC (permalink / raw)


> type Integer_Access is access Integer;
> type T(D: access Integer) is Ada.Limited_Controlled with null record;
>
> procedure Finalize(Object: in out T) is
>   -- Error: cannot convert access discriminant to non-local access type
>   D: Integer_Access := Integer_Access(Object.D);
>...
> What to do? It seems being a serious deficiency in Ada or there are a
> workaround?
  Yet another case where "I can't easily shoot myself in the foot" is
misinterpreted as "a serious deficiency in Ada".  In my experience, if Ada
tells you something is not legal, closer examination will usually show
that it really wasn't a good design idea anyway.
  Since objects of type Integer_Access could be declared more globally
than objects of type T, the Finalize routine might have included
  Global_Variable_Ptr := D;
which would leave Global_Variable_Ptr pointing to unallocated memory.
This error message shows that Ada is preventing that nasty error.  Other
messages have shown how you can get around it.  You can still shoot
in the direction of your foot, but you have to work to do it.
> begin
>   Free(D);
> end;

  In this case, you can shoot safely away from your foot with
Christoph Grein's suggested:
> procedure Finalize (Object: in out T) is
>   type Integer_Ptr is access all Integer;
>   procedure Free is new Ada.Unchecked_Deallocation (Integer, Integer_Ptr);
>   P: Integer_Ptr := Integer_Ptr (Object.D);
> begin
>   Free (P);
> end Finalize;

I seems to me that you needn't worry that
> Because of storage pools for Integer_Ptr may be different
> from storage pool used by "new".
because you get a standard storage pool unless you specify otherwise, so
> type T(D: access Integer)
>   type Integer_Ptr is access all Integer;
should both refer to the same storage pool.



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 20:49   ` tmoran
@ 2003-02-13 21:17     ` Simon Wright
  2003-02-14  4:16       ` tmoran
  2003-02-14  8:28     ` Victor Porton
  1 sibling, 1 reply; 15+ messages in thread
From: Simon Wright @ 2003-02-13 21:17 UTC (permalink / raw)


tmoran@acm.org writes:

> I seems to me that you needn't worry that
> > Because of storage pools for Integer_Ptr may be different
> > from storage pool used by "new".
> because you get a standard storage pool unless you specify otherwise, so
> > type T(D: access Integer)
> >   type Integer_Ptr is access all Integer;
> should both refer to the same storage pool.

I don't see how you can be sure that D.all is allocated from the same
pool as 'access all Integer'? (a bit odd anyway, if you say 'access
*all* ' you imply that blind deallocation is iffy).



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 21:17     ` Simon Wright
@ 2003-02-14  4:16       ` tmoran
  2003-02-14 21:30         ` Simon Wright
  0 siblings, 1 reply; 15+ messages in thread
From: tmoran @ 2003-02-14  4:16 UTC (permalink / raw)


> > > type T(D: access Integer)
> > >   type Integer_Ptr is access all Integer;
> > should both refer to the same storage pool.
>
> I don't see how you can be sure that D.all is allocated from the same
> pool as 'access all Integer'? (a bit odd anyway, if you say 'access
> *all* ' you imply that blind deallocation is iffy).
  The "all" is indeed distracting here, but the original posting showed
that the sole possible variable of the type was a copy of the
discriminant, so Free is OK.
>   type Integer_Ptr is access all Integer;
>...
>   P: Integer_Ptr := Integer_Ptr (Object.D);
According to Cohen 2nd ed p 361, Integer_Ptr cannot be a pool-specific
access type.  And how would you make the anonymous access type
"D: access Integer" allocate from other than the standard pool?



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

* Re: Pitfall: freeing access discriminants
@ 2003-02-14  6:02 Grein, Christoph
  0 siblings, 0 replies; 15+ messages in thread
From: Grein, Christoph @ 2003-02-14  6:02 UTC (permalink / raw)
  To: comp.lang.ada

>   In this case, you can shoot safely away from your foot with
> Christoph Grein's suggested:
> > procedure Finalize (Object: in out T) is
> >   type Integer_Ptr is access all Integer;
> >   procedure Free is new Ada.Unchecked_Deallocation (Integer, Integer_Ptr);
> >   P: Integer_Ptr := Integer_Ptr (Object.D);
> > begin
> >   Free (P);
> > end Finalize;
> 
> I seems to me that you needn't worry that
> > Because of storage pools for Integer_Ptr may be different
> > from storage pool used by "new".
> because you get a standard storage pool unless you specify otherwise, so
> > type T(D: access Integer)
> >   type Integer_Ptr is access all Integer;
> should both refer to the same storage pool.

Hm, I wouldn't be so sure... Better to consult the implementor's manuals. There is nothing in the RM that prevents an implementation from selecting different 
"standard" storage pools for objects allocated for access types and those 
allocated for access discriminants.

Gnat for instance uses different pools depending on the kind of allocation, so 
cannot be sure that access types without a named pool use the same pool.



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

* Re: Pitfall: freeing access discriminants
@ 2003-02-14  6:21 Grein, Christoph
  0 siblings, 0 replies; 15+ messages in thread
From: Grein, Christoph @ 2003-02-14  6:21 UTC (permalink / raw)
  To: comp.lang.ada

> >   type Integer_Ptr is access all Integer;
> >...
> >   P: Integer_Ptr := Integer_Ptr (Object.D);
> According to Cohen 2nd ed p 361, Integer_Ptr cannot be a pool-specific
> access type.  And how would you make the anonymous access type
> "D: access Integer" allocate from other than the standard pool?

There are some statements in the AARM that you have to deallocate with an access 
ess type that has the same storage pool as the one the object was allocated 
with. Without specifying that two access types accessing the same type actually 
use the same pool (via specifying the pool of the second access type: "for 
P2'Storage_Pool use P1'Storage_Pools;" - not sure of the syntax), you rely on 
the mercy of the compiler implementers.

You might experience the nasal demons 
effect...



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

* Re: Pitfall: freeing access discriminants
  2003-02-13 20:49   ` tmoran
  2003-02-13 21:17     ` Simon Wright
@ 2003-02-14  8:28     ` Victor Porton
  2003-02-22 19:00       ` Robert A Duff
  1 sibling, 1 reply; 15+ messages in thread
From: Victor Porton @ 2003-02-14  8:28 UTC (permalink / raw)


In article <kxT2a.99958$be.71860@rwcrnsc53>,
	tmoran@acm.org writes:
>   In this case, you can shoot safely away from your foot with
> Christoph Grein's suggested:
>> procedure Finalize (Object: in out T) is
>>   type Integer_Ptr is access all Integer;
>>   procedure Free is new Ada.Unchecked_Deallocation (Integer, Integer_Ptr);
>>   P: Integer_Ptr := Integer_Ptr (Object.D);
>> begin
>>   Free (P);
>> end Finalize;
> 
> I seems to me that you needn't worry that
>> Because of storage pools for Integer_Ptr may be different
>> from storage pool used by "new".
> because you get a standard storage pool unless you specify otherwise, so
>> type T(D: access Integer)
>>   type Integer_Ptr is access all Integer;
> should both refer to the same storage pool.

In my understanding there may be several standard access pool and the 
pool for access Integer and for Integer_Ptr may be different. Isn't it 
so?



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

* Re: Pitfall: freeing access discriminants
  2003-02-14  4:16       ` tmoran
@ 2003-02-14 21:30         ` Simon Wright
  0 siblings, 0 replies; 15+ messages in thread
From: Simon Wright @ 2003-02-14 21:30 UTC (permalink / raw)


tmoran@acm.org writes:

>               And how would you make the anonymous access type
> "D: access Integer" allocate from other than the standard pool?

I don't see what you mean by "making D allocate". The thing D is
pointing to was allocated by someone from some pool (or perhaps it was
declared aliased).



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

* Re: Pitfall: freeing access discriminants
  2003-02-14  8:28     ` Victor Porton
@ 2003-02-22 19:00       ` Robert A Duff
  0 siblings, 0 replies; 15+ messages in thread
From: Robert A Duff @ 2003-02-22 19:00 UTC (permalink / raw)


porton@ex-code.com (Victor Porton) writes:

> In my understanding there may be several standard access pool and the 
> pool for access Integer and for Integer_Ptr may be different. Isn't it 
> so?

That's correct.  If you don't say "for T'Storage_Pool use...", the
implementation can use any storage pool it likes.  It can put all such
types in the same global heap, or it can create a new pool for each
type, or anything in between.

I think what you want is something like:

    type Int_Ptr is access Integer;

    type T(X: Int_Ptr) is new Limited_Controlled...

Then you can safely deallocate X using an Unchecked_Deallocation for
Int_Ptr.

- Bob




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

end of thread, other threads:[~2003-02-22 19:00 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-02-13 12:41 Pitfall: freeing access discriminants Grein, Christoph
2003-02-13 13:38 ` Victor Porton
2003-02-13 20:49   ` tmoran
2003-02-13 21:17     ` Simon Wright
2003-02-14  4:16       ` tmoran
2003-02-14 21:30         ` Simon Wright
2003-02-14  8:28     ` Victor Porton
2003-02-22 19:00       ` Robert A Duff
  -- strict thread matches above, loose matches on Subject: below --
2003-02-14  6:21 Grein, Christoph
2003-02-14  6:02 Grein, Christoph
2003-02-13 10:04 Victor Porton
2003-02-13 12:07 ` Victor Porton
2003-02-13 13:42   ` Preben Randhol
2003-02-13 17:40 ` Stephen Leake
2003-02-13 19:24   ` Victor Porton

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