[comp.lang.c++] User-controlled allocation/deallocation

wagner@june.cs.washington.edu (Bullwinkle J. Moose) (02/09/88)

Hello out there.  A colleague of mine and I are having a problem that we
would like some net input on.

Suppose that you wish to take complete control of memory allocation and
deallocation for all classes.  (The reason we want to do this is that
we are running multiprocess C++ programs  on a Sequent Balance, and the
shared memory allocation facility is terribly expensive.)
It's easy enough to handle allocation properly:  if this==0, you go
ahead and do the allocation.  That way, if a derived class has already
done the allocation, the base class won't attempt to.

But deallocation is turning out to be very thorny.  About the only control
a programmer has over destructors is that if he sets this=0 in a derived class
destructor, the base class destructor won't get called.  But this isn't
what we want, as the following example shows:

    class Base {
	    Foo *fp;
	    Base *allocate();
	    void deallocate();
	public:
	    Base()	{ if (this==0) this = allocate(); fp = new Foo; }
	    ~Base()	{ delete fp; deallocate(); this = 0; }
    }

    class Derived {
	    Derived *allocate();
	    void deallocate();
	public:
	    Derived()	{ if (this==0) this = allocate(); }
	    ~Derived()	{ deallocate();  this = 0; }
    }

Now if an object of type Base is created and destroyed, everything is fine;
but if an object of type Derived is created and destroyed, ~Base() will
never be called.  This is very bad because the instance of Foo pointed
to by Base::fp will not be deleted, hence the program has a memory leak!
We *want* ~Base() to be called, we just don't want it to call Base::deallocate.

What we really wanted to know is this:  is there any way for ~Base() to
figure out that it shouldn't call Base::deallocate()?  We suspect not.
Perhaps the only way around this is that every class C (including derived
classes) must contain a boolean flag; then C::allocator() can set the
flag and C::deallocator() can check it.  With a hierarchy of classes,
there would be a different flag at each level of the hierarchy, but
only one would ever be set in any given instance (since only one allocator()
call is made).  This is ugly, but it would work all the time.

Another possibility is to have each class provide a cleanup routine that
does everything except memory deallocation.  Then the lowest destructor
in the hierarchy (the only one that gets called) would call it's base
class' cleanup(), which would call it's base class' cleanup(), etc.
Finally, the destructor would do the actual deallocation.

Anyone have any better suggestions?

		Dave Wagner
		University of Washington Comp Sci Department
		wagner@cs.washington.edu
		{ihnp4,harvard,tektronix}!uw-beaver!wagner