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!
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;
}
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?).