Worst Compiler Abuse Ever

I am pretty sure this qualifies as the worst abuse of a compiler I can think of. Note, I am not recommending you use this in production code, lest you wish to be set on fire by those who have to maintain or use your code. Yes, it is that bad.

I was curious as to whether I could create a polymorphic constructor in C++. I wanted to be able to call new Foo, have it call a base class Foo::Foo constructor, but return a pointer to a fully-functional subclass instead.

It turns out that you can do this by abusing the layout of a C++ object at runtime (which is an implementation detail and could vary from compiler to compiler). Generally speaking, C++ classes have their vtable as the first member of the class. All subsequent members follow the vtable. This means you could overlay the subclass over the top of the base class, so long as you follow some strict trickery.

The trick is to use the global placement new operator provided by the STL (or you can write your own if so inclined) so that you can overlay the class memory location. The other trick is to avoid heap corruptions! You do that by overloading the non-placement new for your base class, and have it allocate some “padding” for the subclass member variables.

All told, the monstrosity will look something like this:

#include <new>

#include <stdio.h>
#include <malloc.h>

class Funky {
protected:
  Funky() {}

public:
  explicit Funky( int i );
  virtual ~Funky() { ::printf( "Destroying funky\n" ); }

  void *operator new( size_t size ) {
    return ::malloc( size + 1024 );
  }

  void operator delete( void *ptr ) {
    ::free( ptr );
  }
  
  virtual void Stuff() { ::printf( "Funky\n" ); }
};

class Awesome : public Funky {
  int z;

public:
  Awesome() : z( 1024 ) {}
  virtual ~Awesome() { ::printf( "Destroying awesome\n" ); }

  void Stuff() { ::printf( "Awesome %d\n", z ); }
};

class Amazing : public Awesome {
  double d;

public:
  Amazing() : Awesome(), d( 3.1415 ) {}
  virtual ~Amazing() { ::printf( "Destroying amazing\n" ); }

  void Stuff() { ::printf( "Amazing %f\n", d ); }
};

Funky::Funky( int i ) {
  switch (i) {
  case 1: ::new (this) Awesome; break;
  case 2: ::new (this) Amazing; break;
  }
}

int main( void ) {
  Funky *f = new Funky( 2 );
  f->Stuff();
  delete f;
  return 0;
}

You have to differentiate between the base class constructor which performs the bait and switch, and the base class constructor that does nothing (otherwise the subclasses cannot be instantiated properly).

If you run this, you should see that Amazing::Stuff is called instead of Funky::Stuff. Also, when deleted, you should see Amazing::~Amazing, Awesome::~Awesome and Funky::~Funky, so the class returned truly does behave like everything was kosher!

I wouldn’t recommend using this for anything other than a laugh, but I thought it was pretty interesting.

This entry was posted in C/C++. Bookmark the permalink.

Leave a Reply

Your email address will not be published.