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]

g++: Too deep virtual inherance


Compiler: g++
Versions: 2.91.66 and 2.95.2
System: Solaris
Command line: g++ -o test_virtual -Wall -ggdb -O0 virtual.cpp

The problem: g++ seems to have problem during construction when the inherance is too deep and when this inherance is
virtual:

Result of ./test_virtual execution:
 0xffbef3e4 constructor without argument of class A
 --> 0xffbef3e8 constructor without argument of class B <-- Strange behavior
 0xffbef3f0 constructor of class C
 0xffbef3e0 constructor of class D
 d constructed
 0xffbef3d4 constructor without argument of class A
 0xffbef3d8 constructor of class B
 0xffbef3d0 constructor of class C
 c constructed
 0xffbef3d0 destructor of class C
 0xffbef3d8 destructor of class B
 0xffbef3d4 destructor of class A
 0xffbef3e0 destructor of class D
 0xffbef3f0 destructor of class C
 0xffbef3e8 destructor of class B
 0xffbef3e4 destructor of class A

The good behavior would be:
 0xffbef3e4 constructor without argument of class A
 --> 0xffbef3e8 constructor of class B <--
 0xffbef3f0 constructor of class C
 0xffbef3e0 constructor of class D
 d constructed
 0xffbef3d4 constructor without argument of class A
 0xffbef3d8 constructor of class B
 0xffbef3d0 constructor of class C
 c constructed
 0xffbef3d0 destructor of class C
 0xffbef3d8 destructor of class B
 0xffbef3d4 destructor of class A
 0xffbef3e0 destructor of class D
 0xffbef3f0 destructor of class C
 0xffbef3e8 destructor of class B
 0xffbef3e4 destructor of class A

This test shows that 'c' object construction is correct but not 'd' object construction

The source code: just a file called virtual.cpp:

//*****************************************************************************
// File name: virtual.cpp
// Description: Test a possible bug in g++ about virtual inherance
//*****************************************************************************

// Version tested: 2.91.66 and 2.95.2

// Command line: g++ -o test_virtual -Wall -ggdb -O0 virtual.cpp

// Normal result:
// 0xffbef3e4 constructor without argument of class A
// --> 0xffbef3e8 constructor of class B <--
// 0xffbef3f0 constructor of class C
// 0xffbef3e0 constructor of class D
// d constructed
// 0xffbef3d4 constructor without argument of class A
// 0xffbef3d8 constructor of class B
// 0xffbef3d0 constructor of class C
// c constructed
// 0xffbef3d0 destructor of class C
// 0xffbef3d8 destructor of class B
// 0xffbef3d4 destructor of class A
// 0xffbef3e0 destructor of class D
// 0xffbef3f0 destructor of class C
// 0xffbef3e8 destructor of class B
// 0xffbef3e4 destructor of class A

// Bad result:
// 0xffbef3e4 constructor without argument of class A
// --> 0xffbef3e8 constructor without argument of class B <--
// 0xffbef3f0 constructor of class C
// 0xffbef3e0 constructor of class D
// d constructed
// 0xffbef3d4 constructor without argument of class A
// 0xffbef3d8 constructor of class B
// 0xffbef3d0 constructor of class C
// c constructed
// 0xffbef3d0 destructor of class C
// 0xffbef3d8 destructor of class B
// 0xffbef3d4 destructor of class A
// 0xffbef3e0 destructor of class D
// 0xffbef3f0 destructor of class C
// 0xffbef3e8 destructor of class B
// 0xffbef3e4 destructor of class A

// Bug: a too deep virtual inherance doesn't run correctly during
//      construction.
// Because: c construction is correct but not d construction

#include <iostream>

//*****************************************************************************

class A;
class B;
class C;
class D;

class A
{
public:
  //***************************************************************************
  // Constructors/Destructor
  //***************************************************************************

  //---------------------------------------------------------------------------
  // Name: A
  // Task: Constructor without argument
  //---------------------------------------------------------------------------
  explicit A(void);

  //---------------------------------------------------------------------------
  // Name: ~A
  // Task: Destructor
  //---------------------------------------------------------------------------
  virtual ~A();
};

//*****************************************************************************

class B
  : virtual public A
{
public:
  //***************************************************************************
  // Constructors/Destructor
  //***************************************************************************

  //---------------------------------------------------------------------------
  // Name: B
  // Task: Constructor without argument
  //---------------------------------------------------------------------------
  explicit B(void);

  //---------------------------------------------------------------------------
  // Name: B
  // Task: Constructor with the argument `a'
  //---------------------------------------------------------------------------
  explicit B(const int a);

  //---------------------------------------------------------------------------
  // Name: ~B
  // Task: Destructor
  //---------------------------------------------------------------------------
  virtual ~B();

private:
  //***************************************************************************
  // Implementation
  //***************************************************************************

  //---------------------------------------------------------------------------
  // Name: i
  // Description: an integer variable
  //---------------------------------------------------------------------------
  int i;
};

//*****************************************************************************

class C
  : virtual public B
{
public:
  //***************************************************************************
  // Constructors/Destructor
  //***************************************************************************

  //---------------------------------------------------------------------------
  // Name: C
  // Task: Constructor with the argument `a'
  //---------------------------------------------------------------------------
  explicit C(const int a);

  //---------------------------------------------------------------------------
  // Name: ~C
  // Task: Destructor
  //---------------------------------------------------------------------------
  virtual ~C();
};
//*****************************************************************************

class D
  : virtual public C
{
public:
  //***************************************************************************
  // Constructors/Destructor
  //***************************************************************************

  //---------------------------------------------------------------------------
  // Name: D
  // Task: Constructor with the argument `a'
  //---------------------------------------------------------------------------
  explicit D(const int a);

  //---------------------------------------------------------------------------
  // Name: ~D
  // Task: Destructor
  //---------------------------------------------------------------------------
  virtual ~D();
};

//*****************************************************************************

 //***************************************************************************
// Constructors/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
// Name: A
// Task: Constructor without argument
//---------------------------------------------------------------------------
A::A(void)
{
  cout<<this<<" constructor without argument of class A"<<endl;
}

//---------------------------------------------------------------------------
// Name: ~A
// Task: Destructor
//---------------------------------------------------------------------------
A::~A()
{
  cout<<this<<" destructor of class A"<<endl;
}

//*****************************************************************************

//***************************************************************************
// Constructors/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
// Name: B
// Task: Constructor without argument
//---------------------------------------------------------------------------
B::B(void)
{
  cout<<this<<" constructor without argument of class B"<<endl;
}

//---------------------------------------------------------------------------
// Name: B
// Task: Constructor with the argument `a'
//---------------------------------------------------------------------------
B::B(const int a)
{
  cout<<this<<" constructor of class B"<<endl;
  i=a;
}

//---------------------------------------------------------------------------
// Name: ~B
// Task: Destructor
//---------------------------------------------------------------------------
B::~B()
{
  cout<<this<<" destructor of class B"<<endl;
}

//*****************************************************************************

//***************************************************************************
// Constructors/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
// Name: C
// Task: Constructor with the argument `a'
//---------------------------------------------------------------------------
C::C(const int a)
  :B(a)
{
  cout<<this<<" constructor of class C"<<endl;
}

//---------------------------------------------------------------------------
// Name: ~C
// Task: Destructor
//---------------------------------------------------------------------------
C::~C()
{
  cout<<this<<" destructor of class C"<<endl;
}

//*****************************************************************************

//***************************************************************************
// Constructors/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
// Name: D
// Task: Constructor with the argument `a'
//---------------------------------------------------------------------------
D::D(const int a)
  :C(a)
{
  cout<<this<<" constructor of class D"<<endl;
}

//---------------------------------------------------------------------------
// Name: ~D
// Task: Destructor
//---------------------------------------------------------------------------
D::~D()
{
  cout<<this<<" destructor of class D"<<endl;
}

//*****************************************************************************

//---------------------------------------------------------------------------
// Name: main
// Task: Entry point
//---------------------------------------------------------------------------
int main(int argc,
         char *argv[])
{
  D d(10);
  cout<<"d constructed"<<endl;
  C c(10);
  cout<<"c constructed"<<endl;
  return 0;
}

-- 
François Bertel DIIC3-INC
bertel@ifsic.univ-rennes1.fr
fbertel@irisa.fr
 
Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]