From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,2866100c9a2b8ce7 X-Google-Attributes: gid103376,public From: Jonas Nygren Subject: Re: Free'ing extended types Date: 1996/04/29 Message-ID: <3184D196.310B@ehs.ericsson.se> X-Deja-AN: 152040686 references: <3183AC75.335C@ehs.ericsson.se> <3184803D.1208@ehs.ericsson.se> to: Robert A Duff content-type: text/plain; charset=us-ascii organization: Ericsson Hewlett-Packard Telecommunications AB mime-version: 1.0 newsgroups: comp.lang.ada x-mailer: Mozilla 2.01Gold (WinNT; I) Date: 1996-04-29T00:00:00+00:00 List-Id: Robert A Duff wrote: > > In article <3184803D.1208@ehs.ericsson.se>, > Jonas Nygren 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