Overwriting new and delete
In C++, you can generally use your own stuff if you do not like what you get from the language and standard library: You can overload functions, inherit classes and specialize templates – you can change things into what you want. You do not want to overload &&, || and comma. And you almost never want to overload the global operator new and operator delete.
But I am special, so I do want to.
First, let us recap what ::operator new and ::operator delete really are. (The double colons simply mean that they are in the global namespace, and not in the std namespace. But you probably already knew that.) “Oh, that’s easy,” you might say.” When you say ‘new Foo()‘, you call ::operator new, and when you ‘delete foo’, you call ::operator delete, right?” Wrong. Well, it is true that those operators are called, but they are just two pieces in the big picture. We need to separate between ‘the new expression‘ (sometimes called the new operator), and ‘operator new’.

And so each bit allocated by operator new is flipped to its correct state
Operator new is fairly simple, but comes in many forms. It is responsible for allocating memory, much like malloc(). It has two main forms: operator new and operator new[]. Each of these has three global overloads: The normal version, a nothrow-version and placement new. The latter two are simple: The nothrow variant should return a null pointer if allocation fails, rather than call any new_handlers or throw std::bad_alloc. Placement operator new just returns its pointer argument – it is basically a no-op used to trick the new-expression into calling the constructor for us. Apart from these six global variants, each class can overload its own operator new, thus allowing for an arbitrary number of different ‘operator new’s. The typical reason for overloading operator new is to allow for more efficient memory storage on a per-class basis.
The new-expression is special. There are only two of them: new and new[]. Their mission is to allocate dynamic memory for whatever they are creating and call all the correct constructors. This includes constructors for each object in the case of new[]. The new-expression will also have to call the constructors for base classes or contained classes. They can not be overloaded or replaced.
As usual, Newton’s third law of C++ applies to new and delete – for every new there is an equal and opposite delete. Most of the above is equal (but opposite) for operator delete and the delete-expression.
Normally, if you are not satisfied with ::operator new, then you overload it for your particular class or classes. But for me, the situation is different. I am developing embedded software, and the platform we work on needs to carefully place objects in memory. For C code, this means that we use a function called umalloc() rather than regular malloc(). For C++, we need to ensure that the new-expression gets its memory through umalloc(), which means replacing ::operator new.
Yes, replacing. Not overloading. The global ‘operator new’s and ‘operator delete’s are implicitly declared, and we can replace them simply by providing a new definition. But the behavior of ::operator new is not as straightforward as you might think. You can’t just write:
void* operator new(size_t n) {
void* new_memory = malloc(n);
if (new_memory == nullptr) {
return new_memory;
}
throw std::bad_alloc();
}
As the accepted answer to this question on StackOverflow explains, there is more to it than that, and most of it boils down to new_handlers. I will spare you the boring details (you can read the answer for more information), and simply jump straight to the code I ended up with:
#include <new>
#include <stdexcept>
// Scalar regular new
void* operator new(std::size_t n) throw(std::bad_alloc)
{
using namespace std;
for (;;) {
void* allocated_memory = ::operator new(n, nothrow);
if (allocated_memory != 0) return allocated_memory;
// Store the global new handler
new_handler global_handler = set_new_handler(0);
set_new_handler(global_handler);
if (global_handler) {
global_handler();
} else {
throw bad_alloc();
}
}
}
// Scalar nothrow new
void* operator new(std::size_t n, std::nothrow_t const&) throw()
{
if (n == 0) n = 1;
return malloc(n);
}
// Array regular new
void* operator new[](std::size_t n) throw(std::bad_alloc)
{
return ::operator new(n);
}
// Array nothrow new
void* operator new[](std::size_t n, std::nothrow_t const&) throw()
{
return ::operator new(n, std::nothrow);
}
// Scalar regular delete (doesn't throw either)
void operator delete(void* p) throw()
{
free(p);
}
// Scalar nothrow delete
void operator delete(void* p, std::nothrow_t const&) throw()
{
::operator delete(p);
}
// Array regular delete
void operator delete[](void* p) throw()
{
::operator delete(p);
}
// Array nothrow delete
void operator delete[](void* p, std::nothrow_t const&) throw()
{
::operator delete(p);
}
The reason we have nothrow-versions of operator delete, even when regular delete never throws, is because of the law of equal and opposite news and deletes - when memory has been allocated with nothrow new, it will be deallocated with nothrow delete.
With the exception of any bugs it may contain (I have not found any, so there are probably many left), this should be the typical way to replace ::operator new and ::operator delete. But you almost never want to do that anyway.
Unless you are special.

