Topic: Overloading new() with Multiple Arguments


Author: bgibbons@taligent.com (Bill Gibbons)
Date: Mon, 25 Jul 1994 17:14:14 GMT
Raw View
In article <30n5n8$566@qualcomm.com>, sokeeffe@qualcomm.com wrote:

> class A
> {
> public:
>      A(int i) {};
>      void *operator new(size_t size, void *bufferPtr);
>      void operator delete(void *memPtr) {};
> };
>
> This seemed to work fine with my OS/2 compiler.
>
> I then tried this approach with a second compiler and received an error
> message indicating that I need to supply an new() function which takes
> a single size_t argument.  I assumed the compiler was in error and
> sent in a bug report.  Unfortunately, I am quite used to doing this
> procedure.
>
> Today they responded to me citing p 282 of the ARM which states that an
> implementation is allowed to place a call to a new(size_t size) in a
> constructor.  Furthermore such a new() function MUST be provided in
> this situation since the compiler requires it.

They are wrong.  The full text on page 282 says:

    Here, an implementation is allowed to place a call of operator new()
    in the body of a constructor to implement the constructor semantics.

But since there is no plain operator new in your class, it is not valid
to use a "new" expression without extra arguments, and the semantics to
which the ARM refers do not exist.

This language does not appear in the current working paper.  It was only
commentary in the ARM, clarifying the point that compilers were free to
use this space optimization as long as it did not change the semantics.
Your compiler vendor has changed the semantics, and their compiler should
be fixed.


Bill Gibbons
bgibbons@taligent.com




Author: sokeeffe@qualcomm.com
Date: 22 Jul 1994 01:00:24 GMT
Raw View
The Setup:

I have been developing software in a embedded environment where no
global memory management is available.  Consequently I am overloading
the new and delete operator to efficiently allocate constant size
memory chunks.  I have a few classes that will only be instantiated a
single time in my program.  I wanted to avoid writting a free list
for these objects.  I can't make the objects static because their
constructors require parameters that are not known until run time.
So I tried the following approach using the OS/2 CSet++ environment:

------------

class A
{

public:
     A(int i) {};

     void *operator new(size_t size, void *bufferPtr)
     {
        return bufferPtr;
     };

     void operator delete(void *memPtr) {};
};


static char ABuffer[sizeof(A)];


void main()
{
    A *myAPtr = new( (void *) ABuffer) A(0);
}

------------

My goal was to have control of the timing of the constructor call
on a chunk of memory that had been statically allocated.
I wanted to decouple the allocation of the memory for an object
and the construction of the object in that memory.

This seemed to work fine with my OS/2 compiler.

I then tried this approach with a second compiler and received an error
message indicating that I need to supply an new() function which takes
a single size_t argument.  I assumed the compiler was in error and
sent in a bug report.  Unfortunately, I am quite used to doing this
procedure.

Today they responded to me citing p 282 of the ARM which states that an
implementation is allowed to place a call to a new(size_t size) in a
constructor.  Furthermore such a new() function MUST be provided in
this situation since the compiler requires it.

They classed the problem as a programming error on my part and closed
the bug report.

The Problem:

It seems to me that if an implementation takes this approach then
overloading new() with multiple parameters is useless since the
compiler writter has ordained that new() is called from the constructor
and it may only have a single argument.

I find the example in the ARM on p. 283 disturbing because I would assume
that you would only provide a multiple argument new() if you didn't
want to use the single argument new() operator.  Since I don't have global
memory management, this example is not a "solution" to my problem.

Perhaps I am misunderstanding the implications of the ARM's position but it
appears to give compiler writers the right to effectively prohibit the
use of multiple argument new() operators although it does come out and say
it directly.

I would appreciate further explaination of this issue from more knowledgable
parties then myself.  Am I doing things with the language I shouldn't do?
Or is my compiler vender misintepreting the ARM?

Thanks,

Sean Kevin O'Keeffe
Qualcomm Inc.
sokeeffe@qualcomm.com










Author: maney@MCS.COM (Martin Maney)
Date: 22 Jul 1994 00:49:26 -0500
Raw View
sokeeffe@qualcomm.com wrote:

  [much omitted]

> So I tried the following approach using the OS/2 CSet++ environment:

> My goal was to have control of the timing of the constructor call
> on a chunk of memory that had been statically allocated.
> I wanted to decouple the allocation of the memory for an object
> and the construction of the object in that memory.

> This seemed to work fine with my OS/2 compiler.

> I then tried this approach with a second compiler and received an error

Just prurient interest, but can you tell us which compiler that was?  ;-)

> I find the example in the ARM on p. 283 disturbing because I would assume
> that you would only provide a multiple argument new() if you didn't
> want to use the single argument new() operator.  Since I don't have global
> memory management, this example is not a "solution" to my problem.

> Perhaps I am misunderstanding the implications of the ARM's position but it
> appears to give compiler writers the right to effectively prohibit the
> use of multiple argument new() operators although it does come out and say
> it directly.

I think that what is being said here is that the compiler may code a call
to the default new() function in the constructor, but (and this should
allay your concerns) the call would only be made if it were needed.  I
seem to recall that cfront had some weird and seemingly useless code that
would invoke new() iff the this pointer were null on entry, now I believe
I know what it was for!

Try this: using the troublesome compiler, provide a default new that
makes lots of noise if it gets called and see what happens.  As long as
you never return a null pointer from your new(placement) I would expect
the boobytrapped new() will never be called.