Topic: Finding the right operator new()/delete()


Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Sun, 28 Nov 1993 23:46:03 GMT
Raw View
In article <CGvsFK.1JD@ses.com> jamshid@ses.com (Jamshid Afshar) writes:
>In article <rfgCGqG3A.2ww@netcom.com>,
>Ronald F. Guilmette <rfg@netcom.com> wrote:
>>Note that the ARM say EXPLICITLY at the end of 12.5 that "A destructor
>>finds the operator delete()...".  That statement is in a NON-COMMENTARY
>>part of the ARM, so it constitutes an actual "semantic requirement"
>>(using your terminology) and not merely a statement of one possible
>>implementation technique.  (And I note that the 9/28/93 X3J16 working
>>paper contains essentially similar wording.)
>
>What does "find" mean?

That certainly is *the* question.

>Given that you usually demand very explicit,
>precise language and refuse to allow "common sense" interpretation of
>the ARM, I am surprised that you are interpreting "find" as "calls,
>adhering to usual access rules".

As I tried to point out earlier, it isn't hardly just me whose is making
this interpretation.  It is really various *implementors* (including the
implementors of cfront) who have decided to use this interpretation.

As a matter of fact, I have been arguing rather vigorously that this
interpretation SHOULD NOT BE USED, and that new wording should replace
the old wording which would have the net effect of preventing any and
all implementors from EVER mistakenly trying to use this rather awful
interpretation again.

>Anyway, a language definition can only demand user-observable
>behavior.

I agree.  That's why I provided an example of a piece of code which, when
compiled, elicits very different kinds of "user-observable behavior" from
different existing implementations.

>> #include <stddef.h>
>> struct B1 { void *operator new (size_t); };
>> struct B2 { void *operator new (size_t); };
>> struct D : public B1, public B2 { D(); };
>> D::D () { }
>>More than a few existing C++ compilers actually *fail* to compile this
>>example, claiming that `operator new' is ambiguous.
>>But why?
>
>How should I know?  Ask the compiler writers where the ARM allows this
>behavior.

I have.  They cite the passage at the end of 12.5 which I mentioned earlier.

>I'm really not sure why ANY compiler would choose to implement the
>call to `operator new()' inside of the constructor (which then takes a
>hidden flag) instead of calling `operator new()' inline at the `new'
>expression.

Me neither, but some do.

>Is this a leftover from "assignment to this", or is there
>something funky about virtual bases?  Does it somehow reduce overall
>code size?

As I mentioned previously (in this thread) the reduction in code size was
perhaps the original rationale for implementing things this way, but such
savings are, at best, very minor, and this implementation approach may in
fact *increase* object code size for certain programs.

>>Now you may claim that all of these implementors have merely botched the
>>job, and (as I do) you may claim that there is no excuse for compilers
>>to reject the above code, but given the nearly universal extent to which
>>this particular implementation botch has been mimicked (by implementors)
>
>"Nearly universal"?  Certainly not on the PC.  Borland and Watcom
>compile your code...

Sorry.  I stand corrected.  I'm glad to see that some implementors (at
least) have done this "right".

>Especially if MS allows your code, I'd be extremely surprised if USL
>and GNU could bully the rest of the implementors into breaking their
>compilers.

It isn't a question of "breaking" anyone's compiler.

Judging from the end-product of the X3J11 ANSI C standardization efforts,
it appears that what often happens in these standardization committees is
that when different existing implementations do different things, EVEN WHEN
WHAT SOME OF THEM ARE DOING IS OBVIOUSLY SILLY, the standardization
committee, rather than making any attempt to get wayward implementors to
clean up their acts, will instead pursue the path of least resistance and
form a bland consensus around leaving the case in question in the nebulous
realm of "undefined behavior".  Of course whenever this happens, portability
of code (between "conforming" implementations) becomes a harder thing to
achieve, and end-users are therefore ill-served.

(As a trivial example of what I'm talking about, readers may wish to take
note of the fact that according to the letter of the ANSI/ISO C standard
no diagnostic is strictly required for a declaration like `void a[10];'.
As far as I'm concerned, that tends to illustrate the triumph of compromize
over common sense.)

>Btw, what percentage of voting committee members are compiler writers?

A very high percentage.  More importantly however, as a group, they tend
to be more vocal (and to have more clout) than the folks who represent
end-user constituencies.

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: jimad@microsoft.com (Jim Adcock)
Date: Mon, 29 Nov 1993 18:54:59 GMT
Raw View
In article <CGvsFK.1JD@ses.com> jamshid@ses.com (Jamshid Afshar) writes:
|"Nearly universal"?  Certainly not on the PC.  Borland and Watcom
|compile your code; I don't have MS or Symantec C++.  Anyone?

MS compiles the code.




Author: jamshid@ses.com (Jamshid Afshar)
Date: Mon, 22 Nov 1993 06:52:31 GMT
Raw View
In article <rfgCGqG3A.2ww@netcom.com>,
Ronald F. Guilmette <rfg@netcom.com> wrote:
>Note that the ARM say EXPLICITLY at the end of 12.5 that "A destructor
>finds the operator delete()...".  That statement is in a NON-COMMENTARY
>part of the ARM, so it constitutes an actual "semantic requirement"
>(using your terminology) and not merely a statement of one possible
>implementation technique.  (And I note that the 9/28/93 X3J16 working
>paper contains essentially similar wording.)

What does "find" mean?  Given that you usually demand very explicit,
precise language and refuse to allow "common sense" interpretation of
the ARM, I am surprised that you are interpreting "find" as "calls,
adhering to usual access rules".

Also, the September WP might have reverted, but the June 1993 WP uses
language like "When an object is deleted by a delete-expression, the
deallocation function is LOOKED UP in the scope of class of the
executed destructor" and "Since member allocation and deallocation
functions are static they cannot be virtual.  However, the
deallocation function actually called is DETERMINED by the destructor
actually called".  Even if the ARM required the destructor to call
`operator delete()' (which I don't think it did), the committee seems
to be shying away from that implementation requirement.

Anyway, a language definition can only demand user-observable
behavior.  I don't see how an implementation which used (for example)
an extra vtable entry for `operator delete()' could be deemed
non-conforming (assuming an official standard to conform with).  How
would this be any different from a compiler optimizing away
expressions whose side-effects are not used (is this the "as-if" rule
I've seen mentioned in comp.std.c)?

> #include <stddef.h>
> struct B1 { void *operator new (size_t); };
> struct B2 { void *operator new (size_t); };
> struct D : public B1, public B2 { D(); };
> D::D () { }
>More than a few existing C++ compilers actually *fail* to compile this
>example, claiming that `operator new' is ambiguous.
>But why?

How should I know?  Ask the compiler writers where the ARM allows this
behavior.  The ARM doesn't even say that constructors "find" the
correct `operator new()'!

I'm really not sure why ANY compiler would choose to implement the
call to `operator new()' inside of the constructor (which then takes a
hidden flag) instead of calling `operator new()' inline at the `new'
expression.  Is this a leftover from "assignment to this", or is there
something funky about virtual bases?  Does it somehow reduce overall
code size?

>Now you may claim that all of these implementors have merely botched the
>job, and (as I do) you may claim that there is no excuse for compilers
>to reject the above code, but given the nearly universal extent to which
>this particular implementation botch has been mimicked (by implementors)

"Nearly universal"?  Certainly not on the PC.  Borland and Watcom
compile your code; I don't have MS or Symantec C++.  Anyone?

>I have a STRONG suspicion that rather than requiring something sensible
>(like for instance that compilers accept the above code) X3J16 (which,
>after all, includes a rather large contingent of compiler implementors
>and compiler vendors) is going to instead simply decide to condone this
>bit of "existing practice" and thus officially sanction this exact kind
>of implementation botch as "part of the definition of the language".

Especially if MS allows your code, I'd be extremely surprised if USL
and GNU could bully the rest of the implementors into breaking their
compilers.  Btw, what percentage of voting committee members are
compiler writers?

>I feel so certain that X3J16 will, in the end, simply *standardize* this
>awful language wart (rather than abolishing it) that I'm willing to take
>bets on it.  Any takers?

Okay, if you make it to Austin or I make it to San Jose (right?),
we'll do lunch and the loser picks up the bill.  Do we have to wait
until 1996 or will a draft ruling do ;-)?

The only thing I'm not sure about is whether compilers may require
that declared class-specific `operator new()'s be defined somewhere,
even if they're never called.  I would be disappointed if compilers
were allowed to require the definitions.

Jamshid Afshar
jamshid@ses.com