C++: is "delete (base_class*)this;" safe?
Okay, I've a base class containing a lot of resources and a simple reference counting system for allocating or deallocating those resources as necessary, shared between several derived classes.
I'd failed to consider that if an exception occurs in the constructor of any of the derived classes, the destructor of the base class won't be invoked, and the reference counting system will either at best hold an incorrect (+1) value, or at worst fail to deallocate the resources.
I think that this problem can be solved by catching any exception which occurs in the constructors of the derived classes, invoking "delete (base_class*)this;", and rethrowing the exception.
I'm just wondering whether anybody can confirm whether this is a safe technique? The quick and dirty test below seems to give a safe result, but searching hasn't given me a definitive answer, just the usual dire warnings about mixing C and C++ memory management...
N.b. I know I could circumvent this problem by making the base class an attribute of the derived classes, and if there's no alternative, I will; I'd just prefer a 'prettier' architecture if at all possible...
I'd failed to consider that if an exception occurs in the constructor of any of the derived classes, the destructor of the base class won't be invoked, and the reference counting system will either at best hold an incorrect (+1) value, or at worst fail to deallocate the resources.
I think that this problem can be solved by catching any exception which occurs in the constructors of the derived classes, invoking "delete (base_class*)this;", and rethrowing the exception.
I'm just wondering whether anybody can confirm whether this is a safe technique? The quick and dirty test below seems to give a safe result, but searching hasn't given me a definitive answer, just the usual dire warnings about mixing C and C++ memory management...
Code:
#include <stdio.h>
class A
{
private:
static unsigned int mg_noOfInstances;
// Lots of static pointers.
public:
A( void )
{
// Allocate static pointers if mg_noOfInstances == 0, throw exception if mg_noOfInstances == UINT_MAX.
mg_noOfInstances ++;
printf( "A()\nmg_noOfInstances == %d\n", mg_noOfInstances );
return;
};
virtual ~A( void )
{
mg_noOfInstances --;
// Deallocate static pointers if mg_noOfInstances == 0.
printf( "~A()\nmg_noOfInstances == %d\n", mg_noOfInstances );
return;
};
};
unsigned int A::mg_noOfInstances = 0;
class B : private A
{
public:
B( void )
{
printf( "B()\n" );
// Oh noes! We've encountered an exception; better clean ourselves up before we die...
delete (A*)this;
throw "Oh noes!";
};
};
int main( void )
{
B *b = new B();
return 0;
}Terminal.app Wrote:A()
mg_noOfInstances == 1
B()
~A()
mg_noOfInstances == 0
Abort trap
N.b. I know I could circumvent this problem by making the base class an attribute of the derived classes, and if there's no alternative, I will; I'd just prefer a 'prettier' architecture if at all possible...
Mark Bishop
http://www.parashift.com/c++-faq-lite/ex...l#faq-17.3
Short answer: don't throw exceptions in destructors, don't expect to safely be able to handle exceptions in destructors.
Short answer: don't throw exceptions in destructors, don't expect to safely be able to handle exceptions in destructors.
Measure twice, cut once, curse three or four times.
The destructor of your base class *will* be called if the constructor of a subclass throws:
... so I don't know what your problem is.
Code:
extern "C" void puts(char const *);
class A {
public:
virtual ~A() { puts("~A"); }
};
class B : public A {
public:
B() { throw 1; }
~B() { puts("~B"); }
};
main() { try { B b; } catch(int) { puts("gotcha"); } }Code:
keith$ g++ test.cc
keith$ ./a.out
~A
gotcha... so I don't know what your problem is.
Ugh... Thanks OSC, I finally figured out the difference between your and my code which was causing the difference in behaviour: that the destructor of the base class is only invoked if the exception is caught, which of course is obvious in hindsight
Mark Bishop
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Way to tell what delete is doing? | ia3n_g | 6 | 2,722 |
Aug 26, 2006 12:05 PM Last Post: akb825 |
|

