comp.lang.ada
 help / color / mirror / Atom feed
* Free'ing extended types
@ 1996-04-26  0:00 Jonas Nygren
  1996-04-26  0:00 ` Laurent Guerby
  0 siblings, 1 reply; 26+ messages in thread
From: Jonas Nygren @ 1996-04-26  0:00 UTC (permalink / raw)



I read the following in the RM on unchecked_deallocation:

13.11.2(16)
     .... The execution of a call to an instance of 
     Unchecked_Deallocation is erroneous if the object 
     was created other than by an allocator for an 
     access type whose pool is Name'Storage_Pool. 

I don't quite understand what is written but have a
vague feeling that the code example below could be
labeled 'erroneous execution' by the above paragraph.

Perhaps somebody can answer - is the following code legal:

type a is tagged with .........;
type ap is access all a'class;

procedure free is new unchecked_deallocation(a, ap);

tybe b is new a with .........; -- a is extended

p : ap := new b;

free(p);

Are 'a' and 'b' belonging to the same Name'Storage_Pool?

/jonas




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

* Re: Free'ing extended types
  1996-04-26  0:00 Free'ing extended types Jonas Nygren
@ 1996-04-26  0:00 ` Laurent Guerby
  1996-04-27  0:00   ` Jerry van Dijk
  1996-04-28  0:00   ` Jonas Nygren
  0 siblings, 2 replies; 26+ messages in thread
From: Laurent Guerby @ 1996-04-26  0:00 UTC (permalink / raw)



Jonas Nygren writes
: I read the following in the RM on unchecked_deallocation:
: 
: 13.11.2(16)
:      .... The execution of a call to an instance of 
:      Unchecked_Deallocation is erroneous if the object 
:      was created other than by an allocator for an 
:      access type whose pool is Name'Storage_Pool. 
: 
: I don't quite understand what is written but have a
: vague feeling that the code example below could be
: labeled 'erroneous execution' by the above paragraph.
: 
: Perhaps somebody can answer - is the following code legal:
: 
: type a is tagged with .........;
: type ap is access all a'class;
: 
: procedure free is new unchecked_deallocation(a, ap);
: 
: tybe b is new a with .........; -- a is extended
: 
: p : ap := new b;
: 
: free(p);
: 
: Are 'a' and 'b' belonging to the same Name'Storage_Pool?
: 
: /jonas

   You should ask  your favorite compiler  ;-).  In this case  I don't
think GNAT  is  wrong, and the  error  message is  quite explicit. The
problem is the "all"  in  the access  type  definition, making ap   an
access-to-variable type, see RM95-3.10(10).  Of course if this was not
catched by  some  compile-time   rule, it  would  be    something like
erroneous ;-).

with Ada.Unchecked_Deallocation;
procedure St is

   type a is tagged record X : Integer; end record;
   type ap is access all a'class;

   procedure free is new Ada.unchecked_deallocation(a, ap);

   type b is new a with record
     Y : Integer; end record; -- a is extended

   p : ap := new b;

begin
   free(p);
end St;

guerby@leibniz$ cd ~/ada/tmp/
guerby@leibniz$ gcc -c -gnatvef st.adb
GNAT Compiler Version 3.04w Copyright 1995 Free Software Foundation, Inc.

Compiling: st.adb (source file time stamp: 1996-04-26 21:35:40)

     7.    procedure free is new Ada.unchecked_deallocation(a, ap);
                                                               |
        >>> designated type of actual does not match that of formal "Name"

     7.    procedure free is new Ada.unchecked_deallocation(a, ap);
                                                               |
        >>> instantiation abandoned

    15.    free(p);
           |
        >>> "free" is undefined

 16 lines: 3 errors

Compilation exited abnormally with code 1 at Fri Apr 26 23:35:49

-- 
--  Laurent Guerby, student at Telecom Bretagne (France), Team Ada.
--  "Use the Source, Luke. The Source will be with you, always (GPL)."
--  http://www-eleves.enst-bretagne.fr/~guerby/ (GATO Project).
--  Try GNAT, the GNU Ada 95 compiler (ftp://cs.nyu.edu/pub/gnat).




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

* Re: Free'ing extended types
  1996-04-26  0:00 ` Laurent Guerby
@ 1996-04-27  0:00   ` Jerry van Dijk
  1996-04-28  0:00     ` Robert Dewar
  1996-04-28  0:00   ` Jonas Nygren
  1 sibling, 1 reply; 26+ messages in thread
From: Jerry van Dijk @ 1996-04-27  0:00 UTC (permalink / raw)



Laurent Guerby (Laurent.Guerby@enst-bretagne.fr) wrote:

: GNAT Compiler Version 3.04w Copyright 1995 Free Software Foundation, Inc.
                        ^^^^
That's not fair :-[

:-)

-- 
-----------------------------------------------------------------------
--  Jerry van Dijk       --   e-mail: jerry@jvdsys.nextjk.stuyts.nl  --
--  Banking Consultant   --              Member Team-Ada             -- 
--  Ordina Finance BV    --    Located at Haarlem, The Netherlands   --




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

* Re: Free'ing extended types
@ 1996-04-28  0:00 Jonas Nygren
  1996-04-28  0:00 ` Robert Dewar
  0 siblings, 1 reply; 26+ messages in thread
From: Jonas Nygren @ 1996-04-28  0:00 UTC (permalink / raw)



I forward this on the request of Laurent.

: Laurent Guerby wrote:
: > Jonas Nygren writes
: > : I read the following in the RM on unchecked_deallocation:
: > :
: > : 13.11.2(16)
: > :      .... The execution of a call to an instance of
: > :      Unchecked_Deallocation is erroneous if the object
: > :      was created other than by an allocator for an
: > :      access type whose pool is Name'Storage_Pool.
[deleted]
: Sorry, I got my example code wrong, it should have been:
:
:        procedure free is new unchecked_deallocation(a'Class, 
ap);
:
: 13.11.2(16) talks about 'erroneous execution', i.e. an error 
which the
: compiler can/need not detect. In the example 'p' is a pointer 
to a'class
: and when the call to free is made it actually points to an 
instance of
: type 'b'. So the question is, could this be considered an 
erroneous
: execution?

   I  *think*   that it (erroneous/not  erroneous)   is 
implementation
dependant, because for  each  access  type  the  Storage_Pool  
(if not
user-specified) is choosen  "in an implementation-defined 
manner", see
13.11(17). This has to be documented for each compiler. In the 
case of
GNAT, here is the code for Unchecked_Deallocation :

with System;

procedure Unchecked_Deallocation (X : in out Name) is
   procedure Free (A : System.Address);
   pragma Import (C, Free);

begin
   if X /= null then
      Free (X.all'Address);
      X := null;
   end if;
end Unchecked_Deallocation;

   So there's nothing that could lead  to an erroneous execution 
(note
the X.all'access, the libc then does what's needed).

: /jonas

PS: this  is of general interest, please  post your  correction 
and my
answer to  comp.lang.ada for  verification  (legality stuff   and 
GNAT
stuff) for me, my news server is down this week-end. Thank you.

--
--  Laurent Guerby, student at Telecom Bretagne (France), Team 
Ada.
--  "Use the Source, Luke. The Source will be with you, always 
(GPL)."
--  http://www-eleves.enst-bretagne.fr/~guerby/ (GATO Project).
--  Try GNAT, the GNU Ada 95 compiler 
(ftp://cs.nyu.edu/pub/gnat).




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

* Re: Free'ing extended types
  1996-04-28  0:00 Free'ing extended types Jonas Nygren
@ 1996-04-28  0:00 ` Robert Dewar
  1996-04-29  0:00   ` Laurent Guerby
                     ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Robert Dewar @ 1996-04-28  0:00 UTC (permalink / raw)



Jonas said

"   So there's nothing that could lead  to an erroneous execution
(note
the X.all'access, the libc then does what's needed)."

You seem to have the wrong idea of what erroneous is about. An erroneous
execution is one whose semantics is not specified by the reference
manual. You seem to think this means that it wlil blow up or do 
something wrong. Not at all! It *may* blow up but it does not have to!

You can look at the execution of a particular impementation and conclude
that a particular erroneous execution will have no ill effect on that
implementation, but that does not mean that the exeution is not erroneous!

This is one of these places where no amount of testing can help, only
a detailed knowledge of the formal semantics of the refrence manual
can tell you if a given execution is indeed erroneous -- it is not something
you can (necessarily) observe.






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

* Re: Free'ing extended types
  1996-04-26  0:00 ` Laurent Guerby
  1996-04-27  0:00   ` Jerry van Dijk
@ 1996-04-28  0:00   ` Jonas Nygren
  1 sibling, 0 replies; 26+ messages in thread
From: Jonas Nygren @ 1996-04-28  0:00 UTC (permalink / raw)
  To: Laurent Guerby


Laurent Guerby wrote:
> 
> Jonas Nygren writes
> : I read the following in the RM on unchecked_deallocation:
> :
> : 13.11.2(16)
> :      .... The execution of a call to an instance of
> :      Unchecked_Deallocation is erroneous if the object
> :      was created other than by an allocator for an
> :      access type whose pool is Name'Storage_Pool.
> :
> : I don't quite understand what is written but have a
> : vague feeling that the code example below could be
> : labeled 'erroneous execution' by the above paragraph.
> :
> : Perhaps somebody can answer - is the following code legal:
> :
> : type a is tagged with .........;
> : type ap is access all a'class;
> :
> : procedure free is new unchecked_deallocation(a, ap);
> :
> : tybe b is new a with .........; -- a is extended
> :
> : p : ap := new b;
> :
> : free(p);
> :
> : Are 'a' and 'b' belonging to the same Name'Storage_Pool?
> :
> : /jonas
> 
>    You should ask  your favorite compiler  ;-).  In this case  I don't

Sorry, I got my example code wrong, it should have been:

	 procedure free is new unchecked_deallocation(a'Class, ap);

13.11.2(16) talks about 'erroneous execution', i.e. an error which the
compiler can/need not detect. In the example 'p' is a pointer to a'class
and when the call to free is made it actually points to an instance of
type 'b'. So the question is, could this be considered an erroneous
execution?

Laurent's compilable example:
 
 with Ada.Unchecked_Deallocation;
 procedure St is
 
    type a is tagged record X : Integer; end record;
    type ap is access all a'class;
 
    procedure free is new Ada.unchecked_deallocation(a'class, ap);
						    -- ^ changed to compile
 
    type b is new a with record
      Y : Integer; end record; -- a is extended
 
    p : ap := new b;
 
 begin
    free(p);
 end St;

> --
> --  Laurent Guerby, student at Telecom Bretagne (France), Team Ada.

/jonas




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

* Re: Free'ing extended types
  1996-04-27  0:00   ` Jerry van Dijk
@ 1996-04-28  0:00     ` Robert Dewar
  0 siblings, 0 replies; 26+ messages in thread
From: Robert Dewar @ 1996-04-28  0:00 UTC (permalink / raw)



Jerry said

": GNAT Compiler Version 3.04w Copyright 1995 Free Software Foundation, Inc.
                        ^^^^
That's not fair :-["

Jerry, I know you had a smiley here, but just so people understand. The
w here in 3.04w represents a wavefront development release. We are
continuously testing wavefronts in house and also we release the wavefront
to customers to solve specific problems, and those customers then act
as beta testers for the new release -- basically the way we work is that
most of the time we can find work arounds for problems, but occasionally
there is nothing else that will do other than to fix a problem in the
compiler or to add an enhancement. In this case, we can immediately
get a new version of the compiler out.

The result is that by the time a pubic release is made, the new version
is already field tested. Right now, 3.04 is getting close to release.
We have a few ACVC tests to deal with, and one rather obscure regression.
Once these are out of the way, we will release for Solaris and SGI, and
then the other releases will appear soon after. 

One point to make which we will repeat is thta 3.04 is quite tricky to
build, due to the incorporation of a new approach to exception handling
(which particularly on Solaris and SunOS is a huge improvement in
efficiency). This means following some special build procedures, so those
building from source will need to pay VERY careful attention to the
release notes.





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

* Re: Free'ing extended types
  1996-04-29  0:00     ` Robert A Duff
  1996-04-29  0:00       ` Jonas Nygren
@ 1996-04-29  0:00       ` Robert Dewar
  1996-04-29  0:00         ` Robert A Duff
  1996-05-20  0:00       ` Type conversion between access types (was: Free'ing extended types) Scott Leschke
  2 siblings, 1 reply; 26+ messages in thread
From: Robert Dewar @ 1996-04-29  0:00 UTC (permalink / raw)



Bob Duff said

"Robert is correct in general about erroneousness, but in *this* case,
the RM actually says that it's erroneous on some implementations, and
not others."

Yes indeed, it can be implementation dependent whether or not the semantics
leads to erroneous execution in the case where the semantics is itself
deliberately implementation dependent as in this case.

What I was saying was that you can never look to the actual code in
the implementation to determine this, though you could look to annex M.





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

* Re: Free'ing extended types
  1996-04-28  0:00 ` Robert Dewar
  1996-04-29  0:00   ` Laurent Guerby
@ 1996-04-29  0:00   ` Laurent Guerby
  1996-04-29  0:00     ` Robert A Duff
  1996-04-29  0:00   ` Jonas Nygren
  2 siblings, 1 reply; 26+ messages in thread
From: Laurent Guerby @ 1996-04-29  0:00 UTC (permalink / raw)



Robert Dewar writes
: Jonas said
  ^^^^^ 

   Jonas posted my email  ;-).
: "   So there's nothing that could lead  to an erroneous execution
: (note
: the X.all'access, the libc then does what's needed)."
:
: You seem to have the wrong idea of what erroneous is about. An erroneous
: execution is one whose semantics is not specified by the reference
: manual. You seem to think this means that it wlil blow up or do 
: something wrong. Not at all! It *may* blow up but it does not have to!
: 
: You can look at the execution of a particular impementation and conclude
: that a particular erroneous execution will have no ill effect on that
: implementation, but that does not mean that the exeution is not erroneous!

   I think you missed my answer, I was just saying that, in this case,
the "erroneous execution" was implementation dependant :
 
"  I *think*  that  it   (erroneous/not erroneous)  is  implementation
dependant, because   for each access   type  the Storage_Pool  (if not
user-specified) is  choosen "in an implementation-defined manner", see
13.11(17)."

   And I was pointing out the GNAT sources showing  (I'm not 100% sure
of my interpretation here) the use of one Storage_Pool (coded from the
C  library)  for    all  these types.  My   conclusion   was  that the
construction was not erroneous for the GNAT compiler.

   If another Ada  compiler use different  pools for the  types in the
example, as permitted by the  RM 13.11(17), then  the execution of the
construct is erroneous. Then, of course, it can just work, don't work,
crash your disk or nicely dies with Program_Error ;-).
 
-- 
--  Laurent Guerby, student at Telecom Bretagne (France), Team Ada.
--  "Use the Source, Luke. The Source will be with you, always (GPL)."
--  http://www-eleves.enst-bretagne.fr/~guerby/ (GATO Project).
--  Try GNAT, the GNU Ada 95 compiler (ftp://cs.nyu.edu/pub/gnat).




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

* Re: Free'ing extended types
  1996-04-28  0:00 ` Robert Dewar
@ 1996-04-29  0:00   ` Laurent Guerby
  1996-04-29  0:00     ` Robert A Duff
  1996-04-29  0:00   ` Laurent Guerby
  1996-04-29  0:00   ` Jonas Nygren
  2 siblings, 1 reply; 26+ messages in thread
From: Laurent Guerby @ 1996-04-29  0:00 UTC (permalink / raw)



Jonas Nygren writes
[deleted complete Bob's crystal-clear explanations ;-]
: Yes, I think it would be nice. Every now and then I start thinking
: of defining my own language and implement it always with GC as a 
: basic feature. But then it always stops at the thought because
: of the sheer complexity of the task.
[deleted]

   Note that the impact of a  GC on the  "erronenousness" of a program
is    interesting.  An   Ada run-time  with   GC    can  simply ignore
Unchecked_Dealocation calls, or do smart thing and raise Program_Error
when an access to a previously deallocated object is performed. In the
first case (do  nothing on deallocation)  I think the execution is not
erroneous because RM95-13.11.2(16) says :

"Evaluating  a  name that denotes a  nonexistent  object is erroneous.
The execution  of a call to  an  instance of Unchecked_Deallocation is
erroneous if the object was created other than by  an allocator for an
access type whose pool is Name'Storage_Pool."

   On  a garbage collected implementation,  the object is likely to be
"existant" or your GC is wrong ;-).

: /jonas

-- 
--  Laurent Guerby, student at Telecom Bretagne (France), Team Ada.
--  "Use the Source, Luke. The Source will be with you, always (GPL)."
--  http://www-eleves.enst-bretagne.fr/~guerby/ (GATO Project).
--  Try GNAT, the GNU Ada 95 compiler (ftp://cs.nyu.edu/pub/gnat).




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

* Re: Free'ing extended types
  1996-04-29  0:00       ` Robert Dewar
@ 1996-04-29  0:00         ` Robert A Duff
  0 siblings, 0 replies; 26+ messages in thread
From: Robert A Duff @ 1996-04-29  0:00 UTC (permalink / raw)



In article <dewar.830797117@schonberg>, Robert Dewar <dewar@cs.nyu.edu> wrote:
>What I was saying was that you can never look to the actual code in
>the implementation to determine this, though you could look to annex M.

Yes, quite correct, and quite a useful admonishment.  Too many folks
program by seeing what a particular implementation does, and then
assuming that's what all implementations will do!  I guess I'm off-topic
here, since this affliction is prevalent among programmers in just about
*all* languages, not particularly Ada.  Grump.  ;-)

- Bob




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

* Re: Free'ing extended types
  1996-04-29  0:00   ` Laurent Guerby
@ 1996-04-29  0:00     ` Robert A Duff
  0 siblings, 0 replies; 26+ messages in thread
From: Robert A Duff @ 1996-04-29  0:00 UTC (permalink / raw)



In article <4xrat6vlse.fsf@lagrange.enst-bretagne.fr>,
Laurent Guerby <Laurent.Guerby@enst-bretagne.fr> wrote:
>   If another Ada  compiler use different  pools for the  types in the
>example, as permitted by the  RM 13.11(17), then  the execution of the
>construct is erroneous. Then, of course, it can just work, don't work,
>crash your disk or nicely dies with Program_Error ;-).

Yes, but let's not get too alarmed, here.  If "type Acc1 is access all
T1'Class;" and "type Acc2 is access all T2'Class;", where T2 is a type
extension of T1 (both tagged, of course), then we know (from
accessibility rules) that these two are at the same nesting level, so I
can't imagine any *reason* for the implementation to choose two
different storage pools for Acc1 and Acc2.

In retrospect, I admit we should have *required* Acc1 and Acc2 to share
the same pool.  But if no compiler writers show up saying they don't,
why worry about it?  (And if they do, perhaps the ARG ought to make a
ruling on this point.)

- Bob




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

* Re: Free'ing extended types
  1996-04-29  0:00   ` Laurent Guerby
@ 1996-04-29  0:00     ` Robert A Duff
  1996-04-29  0:00       ` Robert Dewar
  0 siblings, 1 reply; 26+ messages in thread
From: Robert A Duff @ 1996-04-29  0:00 UTC (permalink / raw)



In article <4xpw8qvlau.fsf@lagrange.enst-bretagne.fr>,
Laurent Guerby <Laurent.Guerby@enst-bretagne.fr> wrote:
>   Note that the impact of a  GC on the  "erronenousness" of a program
>is    interesting.  An   Ada run-time  with   GC    can  simply ignore
>Unchecked_Dealocation calls, or do smart thing and raise Program_Error
>when an access to a previously deallocated object is performed. In the
>first case (do  nothing on deallocation)  I think the execution is not
>erroneous because RM95-13.11.2(16) says :
>
>"Evaluating  a  name that denotes a  nonexistent  object is erroneous.
>The execution  of a call to  an  instance of Unchecked_Deallocation is
>erroneous if the object was created other than by  an allocator for an
>access type whose pool is Name'Storage_Pool."
>
>   On  a garbage collected implementation,  the object is likely to be
>"existant" or your GC is wrong ;-).

No, I don't think so.  The RM says an Unchecked_Deallocated object is
non-existent, and deallocating it is erroneous.  If you have a GC that
thinks it still exists, that's fine, but it's irrelevant to the formal
definition of erroneous.  (In this case I'd like the gc to raise an
exception, but of course that's not required, since erroneous means
*anything* can happen, including keeping the officially deallocated
object around and using it as usual.)

- Bob




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

* Re: Free'ing extended types
  1996-04-29  0:00     ` Robert A Duff
@ 1996-04-29  0:00       ` Robert Dewar
  0 siblings, 0 replies; 26+ messages in thread
From: Robert Dewar @ 1996-04-29  0:00 UTC (permalink / raw)



Bob Duff said

"No, I don't think so.  The RM says an Unchecked_Deallocated object is
non-existent, and deallocating it is erroneous.  If you have a GC that
thinks it still exists, that's fine, but it's irrelevant to the formal
definition of erroneous.  (In this case I'd like the gc to raise an
exception, but of course that's not required, since erroneous means
*anything* can happen, including keeping the officially deallocated
object around and using it as usual.)"

Exactly! The definition of what is erroneous and what is not is a function
of the semantics of the language (in some cases, as has been pointed out
it is non-deterministic whether or not the execution is erroneous, since
it depends on implementation choices). But GC does NOT alter the semantics
of unchecked deallocatoin at all, and so is irrelevant to the consideration
of whether or not a program using unchecked deallocation is or is not
erroneous





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

* Re: Free'ing extended types
  1996-04-28  0:00 ` Robert Dewar
  1996-04-29  0:00   ` Laurent Guerby
  1996-04-29  0:00   ` Laurent Guerby
@ 1996-04-29  0:00   ` Jonas Nygren
  1996-04-29  0:00     ` Robert A Duff
  2 siblings, 1 reply; 26+ messages in thread
From: Jonas Nygren @ 1996-04-29  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> Jonas said
> 
> "   So there's nothing that could lead  to an erroneous execution
> (note
> the X.all'access, the libc then does what's needed)."

I think the above quote is from Laurent Guerby.

> 
> You seem to have the wrong idea of what erroneous is about. An erroneous
> execution is one whose semantics is not specified by the reference
> manual. You seem to think this means that it wlil blow up or do
> something wrong. Not at all! It *may* blow up but it does not have to!

Murphy's law: If it can blow up - it will blow up.

I personally take a very simplistic approach to never use a construct
that I know can blow up.

> 
> You can look at the execution of a particular impementation and conclude
> that a particular erroneous execution will have no ill effect on that
> implementation, but that does not mean that the exeution is not erroneous!

Well, I am aiming for portable code and free'ing memory can have great
effect on the program structure. I don't want to have to rewrite my code
between different language implementations. 

> 
> This is one of these places where no amount of testing can help, only
> a detailed knowledge of the formal semantics of the refrence manual
> can tell you if a given execution is indeed erroneous -- it is not something
> you can (necessarily) observe.

That is what my original question was all about. A pity you did not have
an anwer to that - I guess you have the "detailed knowledge of the formal
semantics" of Ada to respond to my question.

I repeat my original question here:

with Ada.Unchecked_Deallocation;
procedure St is
   type a is tagged record X : Integer; end record;
   type ap is access all a'class;
   procedure free is new Ada.unchecked_deallocation(A'class, ap);
   type b is new a with record
     Y : Integer; end record; -- a is extended

   p : ap := new b;
begin
   free(p); -- erroneous ??
end St;

Could the call on free result in erroneous execution (in any conceivable
law abiding implementation of Ada).

/jonas




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

* Re: Free'ing extended types
  1996-04-29  0:00   ` Jonas Nygren
@ 1996-04-29  0:00     ` Robert A Duff
  1996-04-29  0:00       ` Jonas Nygren
                         ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Robert A Duff @ 1996-04-29  0:00 UTC (permalink / raw)



In article <3184803D.1208@ehs.ericsson.se>,
Jonas Nygren  <ehsjony@ehs.ericsson.se> wrote:
>Robert Dewar wrote:
>> You seem to have the wrong idea of what erroneous is about. An erroneous
>> execution is one whose semantics is not specified by the reference
>> manual. You seem to think this means that it wlil blow up or do
>> something wrong. Not at all! It *may* blow up but it does not have to!

Robert is correct in general about erroneousness, but in *this* case,
the RM actually says that it's erroneous on some implementations, and
not others.

>Murphy's law: If it can blow up - it will blow up.

In a way, you're lucky if it *does* blow up.  Sometimes, it works fine.
Until some customer gets ahold of the code, or until somebody tries to
port the code, or you get an updated compiler or something (and the
original programmer has moved to Mars).

>I personally take a very simplistic approach to never use a construct
>that I know can blow up.

Not even by accident?  ;-)

>I repeat my original question here:

OK, I'll try to answer.  Each access type has a storage pool.  Pools can
be shared among many access types.  However, a *single* access type has
exactly one pool.  There is only one access type in your example, so,
clearly everything is allocated in the same pool.  So your example is
*not* erroneous.  The fact that this pool contains A's and B's is
irrelevant -- what matters is the access type.

>with Ada.Unchecked_Deallocation;
>procedure St is
>   type a is tagged record X : Integer; end record;
>   type ap is access all a'class;
>   procedure free is new Ada.unchecked_deallocation(A'class, ap);
>   type b is new a with record
>     Y : Integer; end record; -- a is extended
>
>   p : ap := new b;
>begin
>   free(p); -- erroneous ??
>end St;
>
>Could the call on free result in erroneous execution (in any conceivable
>law abiding implementation of Ada).

No.

However, consider:

with Ada.Unchecked_Deallocation;
procedure St is
   type a is tagged record X : Integer; end record;
   type ap is access all a'class;
   procedure free is new Ada.unchecked_deallocation(A'class, ap);
   type b is new a with record
     Y : Integer; end record; -- a is extended
   type BP is access all B'Class; -- ADDED THIS

   p : BP := new b; -- CHANGED THIS
   q: AP := AP(p); -- ADDED THIS
begin
   free(Q); -- erroneous ?? -- CHANGED THIS
end St;

Now, Q is being freed from a different access type than the one for
which it was allocated.  It is implementation-defined whether or not
this is erroneous!  (Which is subtly different from just being plain old
erroneous.)  This is because it is implementation defined whether AP and
BP share the same pool.  In retrospect, I believe this is a language
design flaw, for obvious reasons.

However, there is probably a de-facto standard.  I would be very
surprised if AP and BP did *not* share the same pool in any
implementation.  (Any implementers care to comment?)

To be safe: Given a hierarchy of tagged types, allocate them all using
the *same* access type.  Then, if necessary, convert this to whatever
other access types you like.  When deallocating, convert things back to
the original access type.  And put all the allocation and deallocation
in a single package, so you easily manage these conventions, and you
won't screw up by mistake.  (That's a good idea anyway -- e.g. you might
want to instrument allocations someday, so you can tell how much memory
you're allocating, or track down storage leaks, or whatever.)

Alternatively, you can say things like "for BP'Storage_Pool use
AP'Storage_Pool;".  Or, you could say "for BP'Storage_Size use 0;",
which will prevent people from accidentally allocating using type BP,
assuming your convention is to always use type AP.

To be safer: Buy a compiler with garbage collection.  ;-)

- Bob




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

* Re: Free'ing extended types
  1996-04-29  0:00     ` Robert A Duff
@ 1996-04-29  0:00       ` Jonas Nygren
  1996-04-29  0:00       ` Robert Dewar
  1996-05-20  0:00       ` Type conversion between access types (was: Free'ing extended types) Scott Leschke
  2 siblings, 0 replies; 26+ messages in thread
From: Jonas Nygren @ 1996-04-29  0:00 UTC (permalink / raw)
  To: Robert A Duff


Robert A Duff wrote:
> 
> In article <3184803D.1208@ehs.ericsson.se>,
> Jonas Nygren  <ehsjony@ehs.ericsson.se> wrote:
> >Robert Dewar wrote:
> >> You seem to have the wrong idea of what erroneous is about. An erroneous
> >> execution is one whose semantics is not specified by the reference
> >> manual. You seem to think this means that it wlil blow up or do
> >> something wrong. Not at all! It *may* blow up but it does not have to!
> 
> Robert is correct in general about erroneousness, but in *this* case,
> the RM actually says that it's erroneous on some implementations, and
> not others.
> 
> >Murphy's law: If it can blow up - it will blow up.
> 
> In a way, you're lucky if it *does* blow up.  Sometimes, it works fine.
> Until some customer gets ahold of the code, or until somebody tries to
> port the code, or you get an updated compiler or something (and the
> original programmer has moved to Mars).
> 
> >I personally take a very simplistic approach to never use a construct
> >that I know can blow up.
> 
> Not even by accident?  ;-)

Well, I actually put in the 'know' to cover my ass :-)

> 
> >I repeat my original question here:
> 
> OK, I'll try to answer.  Each access type has a storage pool.  Pools can
> be shared among many access types.  However, a *single* access type has
> exactly one pool.  There is only one access type in your example, so,
> clearly everything is allocated in the same pool.  So your example is
> *not* erroneous.  The fact that this pool contains A's and B's is
> irrelevant -- what matters is the access type.
> 
> >with Ada.Unchecked_Deallocation;
> >procedure St is
> >   type a is tagged record X : Integer; end record;
> >   type ap is access all a'class;
> >   procedure free is new Ada.unchecked_deallocation(A'class, ap);
> >   type b is new a with record
> >     Y : Integer; end record; -- a is extended
> >
> >   p : ap := new b;
> >begin
> >   free(p); -- erroneous ??
> >end St;
> >
> >Could the call on free result in erroneous execution (in any conceivable
> >law abiding implementation of Ada).
> 
> No.
> 
> However, consider:
> 
> with Ada.Unchecked_Deallocation;
> procedure St is
>    type a is tagged record X : Integer; end record;
>    type ap is access all a'class;
>    procedure free is new Ada.unchecked_deallocation(A'class, ap);
>    type b is new a with record
>      Y : Integer; end record; -- a is extended
>    type BP is access all B'Class; -- ADDED THIS
> 
>    p : BP := new b; -- CHANGED THIS
>    q: AP := AP(p); -- ADDED THIS
> begin
>    free(Q); -- erroneous ?? -- CHANGED THIS
> end St;
> 
> Now, Q is being freed from a different access type than the one for
> which it was allocated.  It is implementation-defined whether or not
> this is erroneous!  (Which is subtly different from just being plain old
> erroneous.)  This is because it is implementation defined whether AP and
> BP share the same pool.  In retrospect, I believe this is a language
> design flaw, for obvious reasons.

Agreed!

> 
> However, there is probably a de-facto standard.  I would be very
> surprised if AP and BP did *not* share the same pool in any
> implementation.  (Any implementers care to comment?)
> 
> To be safe: Given a hierarchy of tagged types, allocate them all using
> the *same* access type.  Then, if necessary, convert this to whatever
> other access types you like.  When deallocating, convert things back to
> the original access type.  And put all the allocation and deallocation
> in a single package, so you easily manage these conventions, and you
> won't screw up by mistake.  (That's a good idea anyway -- e.g. you might
> want to instrument allocations someday, so you can tell how much memory
> you're allocating, or track down storage leaks, or whatever.)
> 
> Alternatively, you can say things like "for BP'Storage_Pool use
> AP'Storage_Pool;".  Or, you could say "for BP'Storage_Size use 0;",
> which will prevent people from accidentally allocating using type BP,
> assuming your convention is to always use type AP.
> 
> To be safer: Buy a compiler with garbage collection.  ;-)

Yes, I think it would be nice. Every now and then I start thinking
of defining my own language and implement it always with GC as a 
basic feature. But then it always stops at the thought because
of the sheer complexity of the task.

> 
> - Bob

Thanks for the complete answer!

/jonas




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

* Type conversion between access types (was: Free'ing extended types)
  1996-04-29  0:00     ` Robert A Duff
  1996-04-29  0:00       ` Jonas Nygren
  1996-04-29  0:00       ` Robert Dewar
@ 1996-05-20  0:00       ` Scott Leschke
  1996-05-21  0:00         ` Dale Stanbrough
  1996-05-21  0:00         ` Robert A Duff
  2 siblings, 2 replies; 26+ messages in thread
From: Scott Leschke @ 1996-05-20  0:00 UTC (permalink / raw)



On a related but different note, I was wondering about the effect of the
reserved word 'all' in the access type declarations below.  First I was
slightly surprised that the type conversions in the example code Bob Duff
posted were allowed since I know that independent access types (even those
specifying the same type) are viewed as denoting separate pools and as such
type conversions between them is not allowed.  This rule appears to go out
the window though if the 'all' modifier is used as in Bob's example.  To
paraphrase Jerry Seinfeld, "What's the deal with that?"

If you remove the 'all's from the declarations, the example ceases to
compile using GNAT 3.03 SunOS 4.1.3 giving the error message:

./pool_test.adb:19:14: invalid conversion, not compatible with type "BP"
defined at line X.

To sumarize:

 with Ada.Unchecked_Deallocation;

 procedure St is
    type a is tagged record X : Integer; end record;

    type ap is access a'class;

    procedure free is new Ada.unchecked_deallocation(A'class, ap);

    type b is new a with record
      Y : Integer; end record; -- a is extended

    type BP is access B'Class; -- ADDED THIS

    p : BP := new b; -- CHANGED THIS
    q: AP := AP(p); -- ADDED THIS

 begin
    free(Q); -- erroneous ?? -- CHANGED THIS
 end St;

gives:

./pool_test.adb:19:14: invalid conversion, not compatible with type "BP"
defined at line X.


BTW, If this is by some off chance highlights a bug in GNAT, please accept
my apologies up front for wasting bandwidth in this forum, but I don't
believe it is.



bobduff@world.std.com (Robert A Duff) writes:

>However, consider:

>with Ada.Unchecked_Deallocation;
>procedure St is
>   type a is tagged record X : Integer; end record;
>   type ap is access all a'class;
>   procedure free is new Ada.unchecked_deallocation(A'class, ap);
>   type b is new a with record
>     Y : Integer; end record; -- a is extended
>   type BP is access all B'Class; -- ADDED THIS

>   p : BP := new b; -- CHANGED THIS
>   q: AP := AP(p); -- ADDED THIS
>begin
>   free(Q); -- erroneous ?? -- CHANGED THIS
>end St;

[..] Other stuff omitted

>- Bob
-- 
Scott Leschke.........................email: leschkes@cig.mot.com
Motorola, Inc............................ph: 847-632-2786
1501 W Shure Drive......................fax: 847-632-3145
Arlington Heights, IL   60004......mailstop: 1301




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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-20  0:00       ` Type conversion between access types (was: Free'ing extended types) Scott Leschke
@ 1996-05-21  0:00         ` Dale Stanbrough
  1996-05-21  0:00           ` Robert A Duff
  1996-05-21  0:00         ` Robert A Duff
  1 sibling, 1 reply; 26+ messages in thread
From: Dale Stanbrough @ 1996-05-21  0:00 UTC (permalink / raw)



Scott Leschke writes:

"First I was
 slightly surprised that the type conversions in the example code Bob Duff
 posted were allowed since I know that independent access types (even those
 specifying the same type) are viewed as denoting separate pools and as such
 type conversions between them is not allowed."


I presume that this also means that access types declared inside a generic
package are not compatable with other access types? 


e.g. 

generic
	type element is private;
package x is

	type ptr is access element;
end;


package y is

	type a is private;

	type ptr is access a;
	
	package new_ptr_package is new x(a);
	
	
end;

Is new_ptr_package.ptr not type convertible with y.ptr?
Is it likely that compilers would use different storage pools for
these two types?

Dale




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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-21  0:00         ` Dale Stanbrough
@ 1996-05-21  0:00           ` Robert A Duff
  0 siblings, 0 replies; 26+ messages in thread
From: Robert A Duff @ 1996-05-21  0:00 UTC (permalink / raw)



In article <4nr20u$mv9@goanna.cs.rmit.EDU.AU>,
Dale Stanbrough  <dale@goanna.cs.rmit.EDU.AU> wrote:
>Is new_ptr_package.ptr not type convertible with y.ptr?

No, it is not convertible.  If you add "all", then it is.

>Is it likely that compilers would use different storage pools for
>these two types?

No.

- Bob




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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-20  0:00       ` Type conversion between access types (was: Free'ing extended types) Scott Leschke
  1996-05-21  0:00         ` Dale Stanbrough
@ 1996-05-21  0:00         ` Robert A Duff
  1996-05-22  0:00           ` Scott Leschke
  1 sibling, 1 reply; 26+ messages in thread
From: Robert A Duff @ 1996-05-21  0:00 UTC (permalink / raw)



In article <leschkes.832628057@ferret>,
Scott Leschke <leschkes@ferret.cig.mot.com> wrote:
>On a related but different note, I was wondering about the effect of the
>reserved word 'all' in the access type declarations below.  First I was
>slightly surprised that the type conversions in the example code Bob Duff
>posted were allowed since I know that independent access types (even those
>specifying the same type) are viewed as denoting separate pools and as such
>type conversions between them is not allowed.  This rule appears to go out
>the window though if the 'all' modifier is used as in Bob's example.  To
>paraphrase Jerry Seinfeld, "What's the deal with that?"

Yes, if you add the 'all' modifier, the restriction goes "out the
window".  You can convert *to* an 'all' access type, so long as the
designated subtypes match.  But you had better be careful about storage
pools -- if you deallocate from the wrong type, it's erroneous.

>If you remove the 'all's from the declarations, the example ceases to
>compile using GNAT 3.03 SunOS 4.1.3 giving the error message:

Right.

>BTW, If this is by some off chance highlights a bug in GNAT, please accept
>my apologies up front for wasting bandwidth in this forum, but I don't
>believe it is.

I believe GNAT is correct here.

- Bob




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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-21  0:00         ` Robert A Duff
@ 1996-05-22  0:00           ` Scott Leschke
  1996-05-23  0:00             ` Robert A Duff
  0 siblings, 1 reply; 26+ messages in thread
From: Scott Leschke @ 1996-05-22  0:00 UTC (permalink / raw)



bobduff@world.std.com (Robert A Duff) writes:

>Yes, if you add the 'all' modifier, the restriction goes "out the
>window".  You can convert *to* an 'all' access type, so long as the
>designated subtypes match.  But you had better be careful about storage
>pools -- if you deallocate from the wrong type, it's erroneous.

So what about 'all' causes the conversion to be allowed?  I looked at
section 4.6 of the LRM but got a tad confused?

-- 
Scott Leschke.........................email: leschkes@cig.mot.com
Motorola, Inc............................ph: 847-632-2786
1501 W Shure Drive......................fax: 847-632-3145
Arlington Heights, IL   60004......mailstop: 1301




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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-22  0:00           ` Scott Leschke
@ 1996-05-23  0:00             ` Robert A Duff
  1996-05-23  0:00               ` progers
  1996-05-24  0:00               ` Scott Leschke
  0 siblings, 2 replies; 26+ messages in thread
From: Robert A Duff @ 1996-05-23  0:00 UTC (permalink / raw)



In article <leschkes.832803959@ferret>,
Scott Leschke <leschkes@ferret.cig.mot.com> wrote:
>So what about 'all' causes the conversion to be allowed?  I looked at
>section 4.6 of the LRM but got a tad confused?

If you write "all", then it's called a "general access type".  4.6(13)
allows conversion from an access type (general or pool-specific) to a
general access type.  4.6(21) says that if the target type doesn't fall
into one the cases allowed previously, then you can only convert within
the same tree of derived types.  (I suspect that derived access types
are unusual, so that would probably not apply.)

In retrospect, I think the added complexity of "all" was a mistake.  We
should have dropped the "all", and just let 4.6(13) apply to any access
type.

The intention of having the "all" in the language was to allow
implementations to use clever representations for pool-specific access
types.  For example, if you know that the storage pool is only 64 K
bytes, then you can use a 16-bit offset for a pool-specific access type,
because you know it always points into that pool.  For a general access
type, however, you need a full pointer (say, 32 bits), because it can
point into any pool, and can point into the stack.

Another advantage of pool-specific access types is that you know you
can't erroneously deallocate from the wrong storage pool.

But in my programs, I almost always end up writing "all".  I suggest
that you always use "all" for access-to-class-wide types, since you will
often need to do the conversions allowed by 4.6(13).

- Bob




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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-23  0:00             ` Robert A Duff
@ 1996-05-23  0:00               ` progers
  1996-05-24  0:00               ` Scott Leschke
  1 sibling, 0 replies; 26+ messages in thread
From: progers @ 1996-05-23  0:00 UTC (permalink / raw)



In <Drv666.92J@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:
>In article <leschkes.832803959@ferret>,
>Scott Leschke <leschkes@ferret.cig.mot.com> wrote:
>>So what about 'all' causes the conversion to be allowed?  I looked at
>>section 4.6 of the LRM but got a tad confused?
>
>If you write "all", then it's called a "general access type".  4.6(13)
>allows conversion from an access type (general or pool-specific) to a
>general access type.  4.6(21) says that if the target type doesn't fall
>into one the cases allowed previously, then you can only convert within
>the same tree of derived types.  (I suspect that derived access types
>are unusual, so that would probably not apply.)

Derived access type conversion is unusual, at least in my experience,
but it sure is handy when you need it (in this case to prevent infinite
recursion on "="):

package Dynamic_Strings is 

  type Text is limited private;
 
  function "="( Left, Right : Text ) return Boolean;

  ...

private

  type Internal is access String;

  type Text is new Internal;

end Dynamic_Strings;



package body Dynamic_Strings is


  function "="( Left, Right : Text ) return Boolean is
  begin
    if ( Internal(Left) = null ) and ( Internal(Right) = null ) then
      return True;
    elsif ( Internal(Left) = null ) xor ( Internal(Right) = null ) then
      return False; -- since one points to an object & the other to nada
    else -- both refer to objects...
      return ( Left.all = Right.all );
    end if;
  end "=";

  ...

end Dynamic_Strings;




pat
---------------
Patrick Rogers
progers@acm.org





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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-23  0:00             ` Robert A Duff
  1996-05-23  0:00               ` progers
@ 1996-05-24  0:00               ` Scott Leschke
  1996-05-24  0:00                 ` Robert A Duff
  1 sibling, 1 reply; 26+ messages in thread
From: Scott Leschke @ 1996-05-24  0:00 UTC (permalink / raw)



bobduff@world.std.com (Robert A Duff) writes:

[...] Some good stuff

>The intention of having the "all" in the language was to allow
>implementations to use clever representations for pool-specific access
>types.  For example, if you know that the storage pool is only 64 K
>bytes, then you can use a 16-bit offset for a pool-specific access type,
>because you know it always points into that pool.  For a general access
>type, however, you need a full pointer (say, 32 bits), because it can
>point into any pool, and can point into the stack.

Yeah, I saw this point made in the Rationale.

>Another advantage of pool-specific access types is that you know you
>can't erroneously deallocate from the wrong storage pool.

>But in my programs, I almost always end up writing "all".  I suggest
>that you always use "all" for access-to-class-wide types, since you will
>often need to do the conversions allowed by 4.6(13).

I have noticed that in most of the code I've seen, all is used pretty
liberally would makes me wonder about the benefit of making the distinction
between pool and general accesss types myself.  I have wondered if it may
have been better to have the distinction go the other way if indeed a
distinction was warranted (ie. general and non-pool based).

-- 
Scott Leschke.........................email: leschkes@cig.mot.com
Motorola, Inc............................ph: 847-632-2786
1501 W Shure Drive......................fax: 847-632-3145
Arlington Heights, IL   60004......mailstop: 1301




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

* Re: Type conversion between access types (was: Free'ing extended types)
  1996-05-24  0:00               ` Scott Leschke
@ 1996-05-24  0:00                 ` Robert A Duff
  0 siblings, 0 replies; 26+ messages in thread
From: Robert A Duff @ 1996-05-24  0:00 UTC (permalink / raw)



In article <leschkes.832959439@ferret>,
Scott Leschke <leschkes@ferret.cig.mot.com> wrote:
>I have noticed that in most of the code I've seen, all is used pretty
>liberally would makes me wonder about the benefit of making the distinction
>between pool and general accesss types myself.  I have wondered if it may
>have been better to have the distinction go the other way if indeed a
>distinction was warranted (ie. general and non-pool based).

I admit, with 20-20 hindsight, that the 'all' thing was a mistake.  I
pushed for the idea during the design of Ada 9X, because I thought this
efficiency distinction was important.  Tucker, on the other hand,
thought that all access types should be 'all'.  He was right; I was
wrong.

- Bob




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

end of thread, other threads:[~1996-05-24  0:00 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-04-28  0:00 Free'ing extended types Jonas Nygren
1996-04-28  0:00 ` Robert Dewar
1996-04-29  0:00   ` Laurent Guerby
1996-04-29  0:00     ` Robert A Duff
1996-04-29  0:00       ` Robert Dewar
1996-04-29  0:00   ` Laurent Guerby
1996-04-29  0:00     ` Robert A Duff
1996-04-29  0:00   ` Jonas Nygren
1996-04-29  0:00     ` Robert A Duff
1996-04-29  0:00       ` Jonas Nygren
1996-04-29  0:00       ` Robert Dewar
1996-04-29  0:00         ` Robert A Duff
1996-05-20  0:00       ` Type conversion between access types (was: Free'ing extended types) Scott Leschke
1996-05-21  0:00         ` Dale Stanbrough
1996-05-21  0:00           ` Robert A Duff
1996-05-21  0:00         ` Robert A Duff
1996-05-22  0:00           ` Scott Leschke
1996-05-23  0:00             ` Robert A Duff
1996-05-23  0:00               ` progers
1996-05-24  0:00               ` Scott Leschke
1996-05-24  0:00                 ` Robert A Duff
  -- strict thread matches above, loose matches on Subject: below --
1996-04-26  0:00 Free'ing extended types Jonas Nygren
1996-04-26  0:00 ` Laurent Guerby
1996-04-27  0:00   ` Jerry van Dijk
1996-04-28  0:00     ` Robert Dewar
1996-04-28  0:00   ` Jonas Nygren

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