[gnu.g++.bug] Virtual Destructor Bug in 1.31.0

kim@cs.sfu.ca (01/26/89)

In using g++ (version 1.31.0) we have encountered a serious problem in the
code generated for virtual destructors.

Criteria: The following code results in runtime infinite recursion on ~derived:

    #include <stdio.h>

    class base
      {
        base();
        virtual ~base();
      };
      
    inline base::base() {}
    inline base::~base() {}
    
    class derived : base
      {
        derived();
        ~derived();
      };
      
    inline derived::derived() : () {}
    inline derived::~derived() { fputc('*',stderr); }
    
    main()
      {
         derived a;
      }
 
The semantics of C++ indicates that the base class destructor is executed
after the derived class destructor code is executed. See:

        Stroustrup, The C++ Programming Language, p. 290
  
        Stroustrup, The Evolution of C++ 1985 to 1987, Proceedings of
        the Usenix C++ Workshop, 1987, p. 10
        
The generated g++ code apparently calls the base class destructor via
the virtual table, rather than directly. This, of course, results in the
infinite recursion.

schmidt@siam.ics.uci.edu (Doug Schmidt) (01/26/89)

In article <8901251939.AA08887@sfu_cmpt.cs.sfu.ca> kim@cs.sfu.ca writes:
++In using g++ (version 1.31.0) we have encountered a serious problem in the
++code generated for virtual destructors.
++
++Criteria: The following code results in runtime infinite recursion on ~derived:
++
++    #include <stdio.h>
++
++    class base
++      {
++        base();
++        virtual ~base();
++      };
++      
++    inline base::base() {}
++    inline base::~base() {}
++    
++    class derived : base
++      {
++        derived();
++        ~derived();
++      };
++      
++    inline derived::derived() : () {}
++    inline derived::~derived() { fputc('*',stderr); }
++    
++    main()
++      {
++         derived a;
++      }
++ 

This bug is fixed in GNU G++ 1.32.  However, your code is also
incorrect, since the constructor's and destructor's are declared in
the ``private'' section of class base and class derived, by the
default visibility rules.

Here's what a beta version of g++ 1.32.1 says:

----------------------------------------
In function struct derived *derived::derived ():
virt-dest-bug.1.32.cc:9: the constructor struct base *base::base () is private
virt-dest-bug.1.32.cc:18: no default constructor defined for type `base'
In function int main ():
virt-dest-bug.1.32.cc:18: the constructor struct derived *derived::derived () is private
virt-dest-bug.1.32.cc:23: no default constructor defined for type `derived'
----------------------------------------

When I added the keyword ``public'' to the classes the program ran as expected.

Doug
--
schmidt@ics.uci.edu (ARPA) |   Per me si va nella citta' dolente.
office: (714) 856-4043     |   Per me si va nell'eterno dolore.
                           |   Per me si va tra la perduta gente.
                           |   Lasciate ogni speranza o voi ch'entrate.