[logo] JX Application Framework
   
Home     
* Cart

Introduction

Why use a framework?

Download

Vision
    API stability

    Code optimization

    Bibliography

Features
    Object messaging

    Extensibility

    Drag-and-Drop

    Networking

    3D Graphics

    Powerful tables

    Styled text editor

    Memory leak debugger

    Tutorial
    Class tree

    Open protocols

    Known bugs

    Next release
    Future plans

    Projects

FAQ

Other software

Log in  

   
     

Bug in gcc 2.9x

The JX Application Framework circumvents the bug by using factory methods (Create()). These functions must be called in place of operator new. The code that would trigger the bug is called inside Create() after the constructor returns.


This bug has been fixed in gcc 3.x. The work arounds in the JX Application Framework will be weeded out once gcc 3.x becomes widely used.

The bug appears to mainly affect Linux systems using glibc, because the optimization that causes the problem is supposedly turned off on most other systems, though nobody seems to know exactly which ones. The easiest way to check is to run the test program listed below.


The following code demonstrates a bug in gcc 2.9x when vtable thunks are turned on.

  B
 / \
A   D - E
 \ /
  C
In the above inheritance tree, B and C inherit virtually from A. When an object of type E is constructed, D's constructor calls a function in A which in turn calls a virtual function overridden by D. This requires a downcast from type A to type D, and egcs incorrectly adjusts the object pointer, forgetting the size of E's member data.

The correct output, produced by gcc 2.7.2, is:

starting test
A::foo  0xbffffb30 1
B::foo  0xbffffb18 1
C::foo  0xbffffb20 1
D::foo  0xbffffb18 1
E::foo  0xbffffb18 1
object constructed
E::foo  0xbffffb18 1
test finished
gcc 2.96 produces the incorrect output shown in bold:
starting test
A::foo  0xbffffb40 1
B::foo  0xbffffb38 1073783288
C::foo  0xbffffb38 1073783288
D::foo  0xbffffb2c 1073783288
E::foo  0xbffffb28 1
object constructed
E::foo  0xbffffb28 1
test finished
The minimal source code required to reproduce the problem is listed below. Changing the size of E's member data changes the difference between the pointer printed by D::foo() and E::foo() by exactly the same amount.


#include <iostream.h>

class A
{
public:

	A() { a=1; bar(); };
	virtual void foo() {
		cout << "A::foo  " << this << ' ' << a << endl; };
	void bar() { foo(); };

private:

	int a;
};

class B : virtual public A
{
public:

	B() { b=1; bar(); };
	virtual void foo() {
		cout << "B::foo  " << this << ' ' << b << endl; };

private:

	int b;
};

class C : virtual public A
{
public:

	C() { c=1; bar(); };
	virtual void foo() {
		cout << "C::foo  " << this << ' ' << c << endl; };

private:

	int c;
};

class D : public B, public C
{
public:

	D() { d=1; bar(); };
	virtual void foo() {
		cout << "D::foo  " << this << ' ' << d << endl; };

private:

	int d;
};

class E : public D
{
public:

	E() { e=1; bar(); };
	virtual void foo() {
		cout << "E::foo  " << this << ' ' << e << endl; };

private:

	int e;
};

int
main()
{
	cout << "starting test" << endl;
	E e;
	cout << "object constructed" << endl;
	e.bar();
	cout << "test finished" << endl;
	return 0;
}

Copyright © 2008 New Planet Software