You can use malloc
/free
for the basic allocation. Handling full
standards compliance for new
is a bit tricky; you need something like:
void*
operator new( size_t n )
{
void* results = malloc( n );
while ( results == NULL ) {
if ( std::get_new_handler() == NULL ) {
throw std::bad_alloc();
}
(*std::get_new_handler())();
results = malloc( n );
}
return results;
}
Often, however, you don't need such full compliance. If you say that
you don't support setting the new_handler
, for example, you can
simplify greatly. In the overloaded version I use for testing, in fact,
if malloc
really fails, I abort (but this version has options to
trigger a failure of new
, on demand, since I want to test that my code
reacts correctly to it as well).
If you're logging, be very careful to avoid endless recursion. The only
functions guaranteed not to use operator new
in the standard library
are malloc
and free
. Of course, a lot have no reason to allocate
dynamically, and I don't worry about functions like memcpy
or
strlen
. In practice, you are probably safe with any of the functions
in the C library (although in theory, printf
could be implemented in
terms of iostream
). But any use of iostream, locale or the standard
containers is out, unless you protect against recursion:
void*
operator new( size_t n )
{
static int recursionCount = 0;
++ recursionCount;
void* results = malloc() ;
// Any additional logic you need...
if ( recursionCount == 1 ) {
logAllocation( results, n );
}
-- recursionCount;
return results;
}
Formally, you should do the same for operator delete
, although in
practice, if you're logging to a file, I wouldn't expect any delete
except in close()
or the destructor.