4

I have the following declaration:

void * operator new (size_t s, PersistentMemory * m) throw()
   {return m->allocatePersistentMemory(s);}

I'm testing memory exhaustion on start-up, which results in m->allocatePersistentMemory(s); returning 0. New then calls the constructor with a null pointer for this

However, based on 3.7.3.1 paragraph 3 of C++ 2003 standard:

An allocation function that fails to allocate storage can invoke the currently installed new_handler (18.4.2.2), if any. [Note: A program-supplied allocation function can obtain the address of the currently installed new_handler using the set_new_handler function (18.4.2.3). ] If an allocation function declared with an empty exception-specification (15.4), throw(), fails to allocate storage, it shall return a null pointer. Any other allocation function that fails to allocate storage shall only indicate failure by throwing an exception of class std::bad_alloc (18.4.2.1) or a class derived from std::bad_alloc.

The way I understand things is that having m->allocatePersistentMemory(s) return null should result in the whole operator new() throw() returning null without calling the constructor. Am I missing some other condition elsewhere that overrides this?

Thanks!

shroudednight
  • 605
  • 4
  • 16

2 Answers2

2

Section 5.3.4 (13) of the C++03 standard says:

[Note: unless an allocation function is declared with an empty exception-specification (15.4), throw(), it indicates failure to allocate storage by throwing a bad_alloc exception (clause 15, 18.4.2.1); it returns a non-null pointer otherwise. If the allocation function is declared with an empty exception-specification, throw(), it returns null to indicate failure to allocate storage and a non-null pointer otherwise. ] If the allocation function returns null, initialization shall not be done, the deallocation function shall not be called, and the value of the new-expression shall be null.

The phrase "initialization shall not be done" implies that the constructor will not be called.

Interestingly -- and unless I am reading the spec wrong -- when your allocation function specifies throw() and returns null, the value of the invocation of "new" itself is null. I had always thought this was impossible (see, for example, pretty much every answer at Will new return NULL in any case?).

Community
  • 1
  • 1
Nemo
  • 70,042
  • 10
  • 116
  • 153
  • Thanks for the additional reference. The environment I work in is exception and standard library phobic, instead using jump buffers (setjmp) ¬.¬ which aren't available at this point, so I had significant incentive to find a work around that wasn't replacing everything with separate allocations, tests, and placement news. – shroudednight Jul 17 '12 at 00:54
2

I suspect you are not calling the new you think you are calling.

This works as you expect.

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}

Where as, this fails.

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
    void * operator new (size_t s) { return myalloc(s); }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}
jxh
  • 69,070
  • 8
  • 110
  • 193
  • This is declared as part of a macro that incorporates a specialized definition of operator new into each class definition, so in this case there is no global `operator new (size_t s, PersistentMemory * m) throw();`. Thanks though :) – shroudednight Jul 17 '12 at 01:04
  • @shroudednight: Still might be a different `new` operator being called though. Placement `new`, or `new[]` should also be checked. – jxh Jul 17 '12 at 01:06
  • Thanks for that extra push, you were right. The macro I expected to be defined for this class wasn't in use and instead had its own custom version. – shroudednight Jul 17 '12 at 01:20
  • @user315052 : why both runs well on VS2010? – Brent81 Oct 13 '12 at 03:28