Skip to content

Instantly share code, notes, and snippets.

@santa4nt
Last active August 29, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save santa4nt/945854f2d261193735b0 to your computer and use it in GitHub Desktop.
Save santa4nt/945854f2d261193735b0 to your computer and use it in GitHub Desktop.
Sample code for overriding operator new/delete in C++.
#include <new>
#include <iostream>
#include <iomanip>
#include <exception>
#include <cstdlib>
// global overrides of new and delete
void* _new(std::size_t);
void* operator new (std::size_t sz)
{
void *mem = _new(sz);
std::cout << std::hex << "::new(0x" << sz << ") => 0x" << mem << std::endl;
return mem;
}
void* operator new (std::size_t sz, unsigned int arg)
{
void *mem = _new(sz);
std::cout << std::hex << "::new(0x" << sz << ") => 0x" << mem;
// showcasing overloading `operator new` with additional parameters
std::cout << "; arg: 0x" << arg << std::endl;
return mem;
}
void* operator new[] (std::size_t sz)
{
void *mem = _new(sz);
std::cout << std::hex << "::new[](0x" << sz << ") => 0x" << mem << std::endl;
return mem;
}
void* _new(std::size_t sz)
{
void *mem = malloc(sz); // returns NULL on failures
if (mem == NULL)
{
throw std::bad_alloc(); // simulate standard C++ new behavior
}
return mem;
}
void operator delete (void *ptr)
{
std::cout << "::delete(0x" << std::hex << ptr << ")" << std::endl;
free(ptr); // nullptr-safe
}
void operator delete (void *ptr, unsigned int arg)
{
std::cout << "::delete(0x" << std::hex << ptr;
// showcasing overloading `operator delete` with additional parameters
std::cout << "; arg: 0x" << arg << ")" << std::endl;
free(ptr); // nullptr-safe
}
void operator delete[] (void *ptr)
{
std::cout << "::delete[](0x" << std::hex << ptr << ")" << std::endl;
free(ptr); // nullptr-safe
}
// class-specific overrides of new and delete
class BaseObj
{
public:
// static is always implicit with operator new(); explicitly stated here for clarity
static void* operator new (std::size_t sz)
{
void *mem = ::operator new (sz); // might throw std::bad_alloc
std::cout << std::hex << "BaseObj::new(0x" << sz << ") => 0x" << mem << std::endl;
return mem;
}
static void* operator new[] (std::size_t sz)
{
void *mem = ::operator new[] (sz);
std::cout << std::hex << "BaseObj::new[](0x" << sz << ") => 0x" << mem << std::endl;
return mem;
}
static void operator delete (void *ptr) noexcept
{
std::cout << "BaseObj::delete(0x" << std::hex << ptr << ")" << std::endl;
::operator delete (ptr);
}
static void operator delete[] (void *ptr) noexcept
{
std::cout << "BaseObj::delete[](0x" << std::hex << ptr << ")" << std::endl;
::operator delete[] (ptr);
}
};
// `new Derived;` will call `BaseObj::operator new`
class Derived : public BaseObj
{
};
// `new C;` will call the global `::operator new`
class C {
private:
char _carr[20];
};
class CExc : public C {
public:
CExc()
{
throw std::exception();
}
};
int main()
{
std::cout << "BaseObj *obj = new Derived;" << std::endl;
BaseObj *obj = new Derived;
std::cout << std::endl;
std::cout << "Derived *objArr = new Derived[10];" << std::endl;
Derived *objArr = new Derived[10];
std::cout << std::endl;
std::cout << "C *obc = new C; // private: char _carr[20];" << std::endl;
C *obc = new C;
std::cout << std::endl;
std:: cout << "C *obc2 = new (0xbeefcafe) C;" << std::endl;
C *obc2 = new (0xbeefcafe) C;
std::cout << std::endl;
std:: cout << "delete obj;" << std::endl;
delete obj;
std::cout << std::endl;
std:: cout << "delete[] objArr;" << std::endl;
delete[] objArr;
std::cout << std::endl;
std:: cout << "delete obc;" << std::endl;
delete obc;
std::cout << std::endl;
// there is no "placement delete" expression; must call explicitly
std:: cout << "::operator delete (obc2, 0xbeefcafe);" << std::endl;
::operator delete (obc2, 0xbeefcafe);
std::cout << std::endl;
try
{
std:: cout << "CExc *ocexc = new (0xdeadbeef) CExc;" << std::endl;
CExc *ocexc = new (0xdeadbeef) CExc;
}
catch (const std::exception&)
{
// placement `operator delete (void*,unsigned int)` should be called here
std::cout << "Caught exception!" << std::endl;
}
return 0;
}
/**
* Sample output:
*
* $ g++ -std=c++11 -o onew onew.cc && ./onew
* -----------------------------------------------------------------------------
* BaseObj *obj = new Derived;
* ::new(0x1) => 0x0x5a1c040
* BaseObj::new(0x1) => 0x0x5a1c040
*
* Derived *objArr = new Derived[10];
* ::new[](0xa) => 0x0x5a1c090
* BaseObj::new[](0xa) => 0x0x5a1c090
*
* C *obc = new C; // private: char _carr[20];
* ::new(0x14) => 0x0x5a1c0e0
*
* C *obc2 = new (0xbeefcafe) C;
* ::new(0x14) => 0x0x5a1c140; arg: 0xbeefcafe
*
* delete obj;
* BaseObj::delete(0x0x5a1c040)
* ::delete(0x0x5a1c040)
*
* delete[] objArr;
* BaseObj::delete[](0x0x5a1c090)
* ::delete[](0x0x5a1c090)
*
* delete obc;
* ::delete(0x0x5a1c0e0)
*
* ::operator delete (obc2, 0xbeefcafe);
* ::delete(0x0x5a1c140; arg: 0xbeefcafe)
*
* CExc *ocexc = new (0xdeadbeef) CExc;
* ::new(0x14) => 0x0x5a1c1a0; arg: 0xdeadbeef
* ::delete(0x0x5a1c1a0; arg: 0xdeadbeef)
* Caught exception!
* -----------------------------------------------------------------------------
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment