I’m trying to implement a technique to test failing operator new described in http://www.codeproject.com/Articles/6108/Simulating-Memory-Allocation-Failure-for-Unit-Test.
This is a sample code being tested:
VArray* arr = new VArray(1U, 3U, true);
I can make new return NULL instead of allocating memory. In this case, the program should continue to next line (which should test if arr == NULL) and this is exactly what it does in MSVC.
However, the constructor of VArray is still called after the failed new in GCC. And since this is NULL, it results in SIGSEGV on the first assignment to a property. This seems to be a wrong behavior according to C++03 standard: https://stackoverflow.com/a/11514528/711006
My implementation of operators new and delete follows.
unsigned int OperatorPlainNewFailsAfter = UINT_MAX;
void* operator new(const size_t _size) throw()
{
void* result;
if(OperatorPlainNewFailsAfter == 0U)
{
result = NULL;
}
else
{
result = malloc(_size);
OperatorPlainNewFailsAfter--;
}
return result;
}
void operator delete(void* _memory) throw()
{
free(_memory);
}
What do I miss?
The C++ standard requires that an allocation function (e.g. the basic operator new) fails by throwing a std::bad_alloc exception, if it fails. It's not allowed to return a nullpointer. When you do return a nullpointer you have Undefined Behavior, and yes, one possible consequence is that a constructor is called.
If the operator new being called is declared throw(), then
it is an error for the compiler to not check for a null pointer.
But it is illegal to declare a non-placement new throw(), so
there's no point in the compiler checking it; if anything, it
should complain when it sees the declaration, because the
non-placement operator new is implicitly declared.
If you want to test for failing new (and it's a good idea),
your operator new function shouldn't return a null pointer,
but should throw std::bad_alloc. Otherwise, you're not
testing the same thing. On the page you site, the test code
uses a placement new instead. The code is still illegal,
because his operator new may return a null pointer without
having declared the function throw(), but that is easily
fixed. (Or not. He calls ::operator new, rather than
malloc, for the actual allocation, and this function may
throw. He also calls the ::operator new function to allocate,
but used the ::delete operator de free; if you call
::operator new to allocate, you should call ::operator
delete to free.) Of course, even fixed, it doesn't test
anything useful, since what you need to know is that your
program reacts correctly to std::bad_alloc, not that it
reacts correctly to a null pointer that it will never see.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With