[gnu.g++.bug] virtual destructors cause execution error for g++

schmidt%blanche.ics.uci.edu@ORION.CF.UCI.EDU ("Douglas C. Schmidt") (10/10/88)

Hi,

  The following program causes a segmentation fault when executed on
Sun 3's and 4's.  The problem appears to be the virtual destructor:

virtual ~Node ( void ) .....

from class Node.  When this is omitted the program works fine.

Readers of the Journal of Object-Oriented Programming will recognize
this as Andrew Koenig's ``dynamic binding'' example from the
August/September issue.  This compiles and executes correctly when
compiled with CC.

----------------------------------------
#include <stream.h>

class Node {
   friend class Tree;
   friend ostream& operator << ( ostream&, const Tree& );

private:
   int Use;
   
protected:      
   Node ( void ) {
      Use = 1;
   }
   virtual void Print ( ostream& ) {
   }
   virtual ~Node ( void ) {  // if this is commented out the program runs ok
   }
};

class Tree {

private:   
   friend class Node;
   friend ostream& operator << ( ostream&, const Tree& );
   Node *Ptr;

public:
   Tree ( int );
   Tree ( char *, Tree );
   Tree ( char *, Tree, Tree );
   Tree ( const Tree& T ) {
      Ptr = T.Ptr; ++Ptr->Use;
   }
   ~Tree ( void ) {
      if ( --Ptr->Use == 0 ) {
         delete Ptr;
      }
   }
   void operator = ( const Tree& T ) {
      ++T.Ptr->Use;
      if ( --Ptr->Use == 0 ) {
         delete Ptr;
      }
      Ptr = T.Ptr;
   }
};

ostream& operator << ( ostream& Stream, const Tree& T ) {
   T.Ptr->Print ( Stream );
   return ( Stream );
}

class Int_Node : public Node {
   friend class Tree;
   
private:
   int Num;
   
   Int_Node ( int K ): Num ( K ) {
   }
   void Print ( ostream& Stream ) {
      Stream << Num;
   }
};

class Unary_Node : public Node {
   friend class Tree;

private:
   char *Operator;
   Tree Operand;
   
   Unary_Node ( char *Op, Tree T ): Operator ( Op ), Operand ( T ) {
   }

   void Print ( ostream& Stream ) {
      Stream << "(" << Operator << Operand << ")";
   }
};

class Binary_Node : public Node {
   friend class Tree;

private:
   char *Operator;
   Tree Left;
   Tree Right;
   
   Binary_Node ( char *Op, Tree T1, Tree T2 ): 
      Operator ( Op ), Left ( T1 ), Right ( T2 ) {
   }

   void Print ( ostream& Stream ) {
      Stream << "(" << Left << Operator << Right << ")";
   }
};

Tree::Tree ( int Num ) {
   Ptr = new Int_Node ( Num );
}

Tree::Tree ( char *Op, Tree T ) {
   Ptr = new Unary_Node ( Op, T );
}

Tree::Tree ( char *Op, Tree T1, Tree T2 ) {
   Ptr = new Binary_Node ( Op, T1, T2 );
}

main () {
   Tree T = Tree ( "*", Tree ( "-", 5 ), Tree ( "+", 3, 4 ) );
   
   cout << T << "\n";
   T = Tree ( "*", T, T );
   cout << T << "\n";   
}
----------------------------------------