This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

dynamic cast bug.



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)
Summary:

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


Description: 

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
{
public:
  B0()
    {
     foo();
    }
  void foo()
    {
     cout
      << this << " "
      << dynamic_cast<O4*>(this) << " "
      << dynamic_cast<O4*>(static_cast<O3*>(this)) << endl;
    }
  int i6_;
};

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

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]