- To: gcc-bugs at gcc dot gnu dot org
- Subject: A bug
- From: Pavel Rousnak <pr at pol dot unibest dot ru>
- Date: Fri, 13 Oct 2000 14:38:07 +0400
Hi!
It seems we have found a bug in gcc under RedHat.
We have extracted a piece of code from our (big) program and created a test.
----------------------------------------------------------------------------
#include <stdio.h>
/*======================================================================*/
/* There are three objects: Base, Middle, Upper
* Middle derived from Base, Upper - from Middle
* There is a virtual method 'check' defined in Base and
* overriden in Middle. It is called twice from within destructor
* of Middle and then called again by method 'close' which in turn
* is called from the same destructor.
* Each time the method is applied to the same object and passed the same
* argument 'src' (equal to 'this' of current object).
* And we have different 'this' inside 'check' in different calls!!!!
*
* The test was built by the command:
* cc -o test test.cc
*
* The test was compiled by gcc 2.96 under RedHat Linux 7.0 (standard)
* We had the same behavior with:
* standard RedHat 6.1
* standard RedHat 6.2
* gcc 2.95 + RedHat 6.2
*
* The test passed successfully under the systems listed below:
* gcc 2.95 + FreeBSD FreeBSD 4.0-STABLE (!!!)
* standard IBM AIX 4.2
* gcc 2.95 + IBM AIX 4.2
*/
/*======================================================================*/
/*======================================================================*/
class Base
{
public:
virtual ~Base() { printf("delete Base %08x\n", this); }
virtual int check(Base *src, int line) { return 0; }
};
/*======================================================================*/
class Middle :
virtual public Base
{
public:
~Middle();
virtual int check(Base *src, int line);
void close();
};
/*======================================================================*/
class Upper :
virtual public Middle
{
public:
~Upper();
};
/*======================================================================*/
Middle::~Middle()
{
printf("delete Middle %08x\n", this);
/* Two lines below: the same method is called by twice... */
check(this, __LINE__);
/* ...but 'this->' at the front of the method causes strange
* value of 'this' in check()... */
this->check(this, __LINE__);
/* 'check' will be called from 'close' and there it fails again */
close();
}
/*======================================================================*/
void Middle::close()
{
printf("close Middle %08x\n", this);
check(this, __LINE__);
}
/*======================================================================*/
/* Compare 'src' and 'this' (they should be equal to each other)
* and print corresponding message
*/
int
Middle::check(Base *src, int line)
{
Base* t = this;
if( t != src ) {
/* Oops: something wrong */
printf("Check failed(this=%08x,line=%d): %08x != %08x!\n",
this, line, t, src);
return 0;
}
else {
/* Ok */
printf("Check Ok(this=%08x,line=%d): %08x\n", this, line, t);
return 1;
}
}
/*======================================================================*/
Upper::~Upper()
{
printf("delete Upper %08x\n", this);
}
/*======================================================================*/
int main(int argc, char **argv )
{
/*
Middle *obj = new Middle;
printf("Middle created: Middle=%08x, Base=%08x\n",
obj, (Base *)obj);
obj->check(obj, __LINE__);
delete obj;
printf("-----------------------\n");
*/
Upper *upper = new Upper;
printf("Upper created: Upper=%08x, Middle=%08x, Base=%08x\n",
upper, (Middle *)upper, (Base *)upper);
/* here 'check' works fine */
upper->check(upper, __LINE__);
/* 'check' will be called by destructor of Middle.
* And it works wrong there :( */
delete upper;
return 0;
}
------------------------------------------------------------------------------
The output of the test:
Upper created: Upper=08051120, Middle=08051128, Base=08051124
Check Ok(this=08051128,line=121): 08051124
delete Upper 08051120
delete Middle 08051128
Check Ok(this=08051128,line=62): 08051124
Check failed(this=08051120,line=65): 08051128 != 08051124!
close Middle 08051128
Check failed(this=08051120,line=75): 08051128 != 08051124!
delete Base 08051124
------------------------------------------------------------------------------
Best regards,
Pavel Rousnak,
Nikolaj Logvinov,