4
\$\begingroup\$

In our embedded application, we have to replace ::operator new and ::operator delete to call a special malloc(), to ensure that the memory is allocated correctly. The code, written with this guide in mind, looks like this:

#include <new>
#include <stdexcept>
// Regular scalar 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();
 }
 }
}
// Nothrow scalar new
void* operator new(size_t n, std::nothrow_t const&) throw()
{
 if (n == 0) n = 1;
 return malloc(n);
}
// Regular array new
void* operator new[](size_t n) throw(std::bad_alloc)
{
 return ::operator new(n);
}
// Nothrow array new
void* operator new[](size_t n, std::nothrow_t const&) throw()
{
 return ::operator new(n, std::nothrow);
}
// Regular scalar delete
void operator delete(void* p) throw()
{
 free(p);
}
// Nothrow scalar delete
void operator delete(void* p, std::nothrow_t const&) throw()
{
 ::operator delete(p);
}
// Regular array delete
void operator delete[](void* p) throw()
{
 ::operator delete(p);
}
// Nothrow array delete
void operator delete[](void* p, std::nothrow_t const&) throw()
{
 ::operator delete(p);
}
// Driver function to make the sample code executable.
int main()
{
 int* x = new int;
 delete x;
 int* y = new int[10];
 delete[] y;
}

Is this code correct?

In particular:

  • Do I need any special alignment handling?
  • Should there be any other differences between operator new and operator new[]?
asked Dec 28, 2011 at 12:19
\$\endgroup\$
1
  • \$\begingroup\$ (This is technically not overloading the operators, but rather to replace them, but I still consider it relevant to the operator-overloading tag.) \$\endgroup\$ Commented Dec 28, 2011 at 12:20

1 Answer 1

3
\$\begingroup\$

I am surprised this compiles and works (it does I test it)

 global_handler();

As global handler is a pointer to a function I was expecting to see this:

 (*global_handler)();

Comments:

Throw specifiers (except no throw) have been deprecated in the latest standard.
So you should probably follow their lead in that

void* operator new(std::size_t n) throw(std::bad_alloc)

The array version of new calls the no-throw version of new.

void* operator new[](size_t n, std::nothrow_t const&) throw()

Thus you are not getting the benefits of any registered out of memory handlers. Maybe you should just call the normal version of new so that the out of memory handlers are called for arrays as-well.

Do I need any special alignment handling?

No. malloc() provides memory that is aligned for any type.
http://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html

Should there be any other differences between operator new and operator new[]?

No. Apart from not using the out of memory handlers it looks fine.

answered Dec 28, 2011 at 17:47
\$\endgroup\$
1
  • \$\begingroup\$ Thank you. I think the normal function call syntax is clearer, and is valid syntax even though it is a function pointer. I wrote the functions without the throw specifiers at first, exactly because of them being deprecated in C++0xb, but then the code wouldn't compile. (Maybe I had too strict warnings.) I will fix the regular operator new[] to correspond with regular operator new. Thanks again! \$\endgroup\$ Commented Dec 28, 2011 at 23:09

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.