[omniORB] MSVC 5.0 bug: throw in ctor with virtual base class calls virtual
base with wrong 'this'
Dietmar May
dcmay@object-workshops.com
Thu, 3 Sep 1998 22:02:02 -0700
Ran across this bug while debugging a program. Since it deals with
calling the destructor of a virtual base class, which CORBA uses a
little bit :-), thought it might be of interest to others.
Essentially, if an exception is thrown by the constructor of a derived
class (where apparently there is at least one level of intermediate
derivation), the virtual base class' destructor is called with a 'this'
pointer that is offset by 4 or more bytes. A second side effect, at
least in the test program below, is that the virtual base class'
destructor is called a second time with the correct this pointer! This,
of course, is a problem if the virtual base class has any data to clean
up, because integers may become pointers, and pointers may reference
other objects...
Sorry, there are no known work-arounds. Also, see MS Q168936
Knowledge-base article.
=============================
#include <stdio.h>
class base
{
public:
base ()
{
printf("base::base() this = 0x%lx\n", (long)(void*)this);
i = 0;
}
virtual ~base ()
{
printf("base::~base() this = 0x%lx\n", (long)(void*)this);
i = 0;
}
protected:
int i;
};
class intermed : public virtual base
{
public:
intermed ()
{
printf("intermed::intermed () this = 0x%lx\n",
(long)(void*)this);
j = 0;
i = 1;
}
virtual ~intermed ()
{
printf("intermed::~intermed () this = 0x%lx\n",
(long)(void*)this);
j = 0;
}
protected:
int j;
};
class derived : public intermed
{
public:
derived ()
{
printf("derived::derived() this = 0x%lx\n", (long)(void*)this);
k = 0;
j = 1;
throw int(0);
k = 1;
}
~derived ()
{
printf("derived::~derived() this = 0x%lx\n", (long)(void*)this);
k = 0;
}
protected:
int k;
};
int main ()
{
try
{
printf("creating derived object\n");
derived d;
}
catch(...)
{
printf("caught exception from ctor\n");
}
printf("out of catch block\n");
return 0;
}
=============================
Running this code results in the following output under NT 4.0 sp3:
creating derived object
base::base() this = 0x12ff68
intermed::intermed () this = 0x12ff5c
derived::derived() this = 0x12ff5c
intermed::~intermed () this = 0x12ff5c
base::~base() this = 0x12ff64
base::~base() this = 0x12ff68
caught exception from ctor
out of catch block
Regards,
Dietmar May
Software Architect
Object Workshops, Inc.
http://www.object-workshops.com
dcmay@object-workshops.com