Topic: Operator new called twice when overrode and failured ?


Author: iseg@arcady.msk.su (Ilya Segalovich)
Date: Sun, 24 May 92 10:56:03 +0300
Raw View
  I have the following program segment compiled under Borland C++ 2.0:
(the same effect under 3.0)

----------------------------------------------------------------------
class someClass {

   void* operator new( size_t);
      // new #1
      // should(!) be defined because only it is called from constructors

   void* operator new( size_t, anything_else);
      // new #2

   someClass( /*...*/);
      // some constructor

};

/*...*/

anything_else x;
someClass*    ptr;

/*...*/

ptr = new( x) someClass( /*...*/);            // new #2 desired

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

   Looking at Assembler text I have realized that the following action
takes place actually (I try to express this code below in a pseudo-C++ style):

ptr = someClass::someClass( someClass::new( sizeof( someClass), x), /*...*/);

   As you can see, a correct call of new is made, which might
be unsuccessfull (by many reasons).
   However call to another (default) operator new from inside
a constructor (!) with the default set of parameters can be successfull
and returns overall success as a result.

   But in fact this is elusive -- it is obtained by an improper
version of new.

   The way the constructor calls "new" is also taken from Assembler text
and is shown below.

someClass* someClass::someClass( someClass* this, /*...*/) {
   if (!this)
      this = someClass::new( sizeof( someClass)); // new #1 always
   if (!this)
      return this;
   {
      /*...explicitly given actions... */
   }
   return this;
}

   This difference might be sufficient in cases when, for example,
two versions of new
   - allocate different amounts of memory or
   - allocate space in different types of memory,
depending on second, third and other parameters.

   Note that when we call the default new somewhere in a program:

ptr = new someClass( /*...*/);       // new #1 desired

the explicit new call is not generated, and only
an implicit built-in-constructor "new" call is made.
The result looks as follows:

ptr = someClass::someClass( 0, /*...*/);

   I failed to find this topic in a literature available
to me (Borland C++ manuals and Straustrup 2-nd ed.). Thus
I have the following questions to everybody willing to deep
inside these questions:

   1. Is the double call of new a part of some standart
or is it a Borland specific?
   2. What must I do (not leaving C++ concepts) in that cases when
I need to be sure that the proper version of new is used ?

   Thank you in advance.
   Sincerely,

   Ilya Segalovich.