dynamic cast bug.

Karl Nelson kenelson@ece.ucdavis.edu
Sat Jun 24 17:05:00 GMT 2000

Category: c++
Class: wrong-code 
Version: all  (2.8.1, egcs, 2.95, 2.95.2, 2.95.3 tested)
Architecture: all (Sun, HP-UX, Irix, i86 tested)

dynamic_cast with during a constructor when the base class
uses virtual inheritance and a derived class uses multiple inheritance
yields an incorrect result.


This bug was reported as a segfualt in the gtk-- C++ library. 
Further tracing lead us to believe that the error was in fact
a function of the compiler.

With certain class structures it is possible for dynamic_cast to
return an incorrect pointer during the constructor.  The bug does
not occur on any non-gcc compilers but has been verified to exist
up to 2.95.3.   Static cast does not display that behavior.
Following construction casting works as expected.  Likely this is a 
bug in the vtable.  

The requirements for causing the bug to appear are lengthy.  There
must be a virtual inheritence earlier in the base classes and a 
derived class must have multiple inheritence.  A cast must happen
to one of the base classes which then is dynamic cast back up to
another base class.  Since this cast is to a fully constructed 
base class this should work properly. 

Example program:
The code below demostrates the error.  The proper output is 
to print the same pointer location 9 times.  However, on 
gcc the code produces

0x804a830 0x804a830 0x804a838
0x804a830 0x804a830 0x804a830
0x804a830 0x804a830 0x804a830

Thus one can see that a dynamic cast from a proper base class
resulted in an incorrect pointer.  The error only occurs during
construction of B0.  Gtk-- unforunately execises this bug 
on many programs. 

O1-5 represent structures defined in the shared library gtk--.
B0-1 combine them to expose the bug.

#include <iostream.h>

struct O1 { int i0_; virtual ~O1() {} };
struct O2 : virtual public O1 { int i1_; virtual ~O2() {} };
struct O3 : public O2 { int i2_; O3() {} virtual ~O3() {} };
struct O4 : public O3 { int i4_; };
struct O5 { int i5_; O5(){} };

class B0 : public O4
  void foo()
      << this << " "
      << dynamic_cast<O4*>(this) << " "
      << dynamic_cast<O4*>(static_cast<O3*>(this)) << endl;
  int i6_;

class B1 : public B0, public O5
  B1() { }
  int i7_;

int main()
  B1 *p = new B1;
  B0 *b= p;
    << p << " "
    << dynamic_cast<O4*>(p) << " "
    << dynamic_cast<O4*>(static_cast<O3*>(p)) << endl;
  return 0

More information about the Gcc-bugs mailing list