g++: Too deep virtual inherance
Francois Bertel
fbertel@irisa.fr
Thu Jan 13 06:21:00 GMT 2000
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
ÃÂ
More information about the Gcc-bugs
mailing list