Thread overview
Incorrect stack unwinding when exception is thrown
Mar 26, 2002
stevetao
Mar 26, 2002
Jan Knepper
Mar 26, 2002
SteveTao
Mar 26, 2002
Jan Knepper
Mar 26, 2002
Walter
March 26, 2002
DM 8.27 does not correctly unwind the stack when exception is thrown.  The result of the following code should be.

Composite is created
Element no. 1 is created
Element no. 2 is created
Element no. 3 is created
Element no. 4 is created
Element no. 5 is created
Element no. 6 is created
Element no. 5 is destroyed
Element no. 4 is destroyed
Element no. 3 is destroyed
Element no. 2 is destroyed
Element no. 1 is destroyed
Exception is thrown

But DM 8.27 generate the following:

Composite is created
Element no. 1 is created
Element no. 2 is created
Element no. 3 is created
Element no. 4 is created
Element no. 5 is created
Element no. 6 is created
Exception is thrown

The code to demonstrate this problem is

#include <iostream.h>

struct Exception {};

//--------------------------------------------------------------
class Element
{
public:
Element()
{
cout << "Element no. " << ++count << " is created\n";
if (count > 5)
{
--count;
throw Exception();
}
}
virtual ~Element()
{
cout << "Element no. " << count-- << " is destroyed\n";
}
private:
static int count;
};

int Element::count = 0;

//--------------------------------------------------------------
class Composite
{
public:
Composite()
{
cout << "Composite is created\n";
pE = new Element[10];
}
virtual ~Composite()
{
delete [] pE;
cout << "Composite is destroyed\n";
}
private:
Element *pE;
};

//--------------------------------------------------------------
class Base
{
public:
Base()
{
pC = new Composite;
cout << "Constructing base\n";
}
virtual ~Base()
{
delete pC;
cout << "Destroying base\n";
}
private:
Composite *pC;
};

//--------------------------------------------------------------
class Derived : public Base
{
public:
Derived()
{
cout << "Constructing derived\n";
throw Exception();
}
virtual ~Derived()
{
cout << "Destroying derived\n";
}
};

//--------------------------------------------------------------
// main
//--------------------------------------------------------------
int main()
{
Base * p;

try {
p = new Derived;
}
catch( Exception e) {
cout << "Exception is thrown\n";
}

return 0;
}


March 26, 2002
I am not sure if this is stack unwinding or the fact that you throw an exception during a new [] which does not revert the contructions by destructing the constructed elements.

Jan



stevetao wrote:

> DM 8.27 does not correctly unwind the stack when exception is thrown.  The result of the following code should be.
>
> Composite is created
> Element no. 1 is created
> Element no. 2 is created
> Element no. 3 is created
> Element no. 4 is created
> Element no. 5 is created
> Element no. 6 is created
> Element no. 5 is destroyed
> Element no. 4 is destroyed
> Element no. 3 is destroyed
> Element no. 2 is destroyed
> Element no. 1 is destroyed
> Exception is thrown
>
> But DM 8.27 generate the following:
>
> Composite is created
> Element no. 1 is created
> Element no. 2 is created
> Element no. 3 is created
> Element no. 4 is created
> Element no. 5 is created
> Element no. 6 is created
> Exception is thrown
>
> The code to demonstrate this problem is
>
> #include <iostream.h>
>
> struct Exception {};
>
> //--------------------------------------------------------------
> class Element
> {
> public:
> Element()
> {
> cout << "Element no. " << ++count << " is created\n";
> if (count > 5)
> {
> --count;
> throw Exception();
> }
> }
> virtual ~Element()
> {
> cout << "Element no. " << count-- << " is destroyed\n";
> }
> private:
> static int count;
> };
>
> int Element::count = 0;
>
> //--------------------------------------------------------------
> class Composite
> {
> public:
> Composite()
> {
> cout << "Composite is created\n";
> pE = new Element[10];
> }
> virtual ~Composite()
> {
> delete [] pE;
> cout << "Composite is destroyed\n";
> }
> private:
> Element *pE;
> };
>
> //--------------------------------------------------------------
> class Base
> {
> public:
> Base()
> {
> pC = new Composite;
> cout << "Constructing base\n";
> }
> virtual ~Base()
> {
> delete pC;
> cout << "Destroying base\n";
> }
> private:
> Composite *pC;
> };
>
> //--------------------------------------------------------------
> class Derived : public Base
> {
> public:
> Derived()
> {
> cout << "Constructing derived\n";
> throw Exception();
> }
> virtual ~Derived()
> {
> cout << "Destroying derived\n";
> }
> };
>
> //--------------------------------------------------------------
> // main
> //--------------------------------------------------------------
> int main()
> {
> Base * p;
>
> try {
> p = new Derived;
> }
> catch( Exception e) {
> cout << "Exception is thrown\n";
> }
>
> return 0;
> }

March 26, 2002
The code I provided was to demonstrate that if the exception is thrown during the operator new [], the destructor of all created objects must be called.

The code was working correctly with the following compilers:
1. Microsoft Visual C++ 6.0 - 7.0
2. Borland C++ 5.02 - 5.5.1
3. GNU GCC 2.95.0 - 3.04
4. Watcom C++ 11.0c
5. Metrowerks CodeWarrior 5 - 7

All these compilers properly called the destructor of all created objects if the exception is thrown during the operator new [].  I originally guessed that the problem was due to incorrect stack unwinding.

Steve

In article <3CA0B5E6.271CE29F@smartsoft.cc>, Jan Knepper says...
>
>I am not sure if this is stack unwinding or the fact that you throw an exception during a new [] which does not revert the contructions by destructing the constructed elements.
>
>Jan
>


March 26, 2002
SteveTao wrote:

> The code I provided was to demonstrate that if the exception is thrown during the operator new [], the destructor of all created objects must be called.
>
> The code was working correctly with the following compilers:
> 1. Microsoft Visual C++ 6.0 - 7.0
> 2. Borland C++ 5.02 - 5.5.1
> 3. GNU GCC 2.95.0 - 3.04
> 4. Watcom C++ 11.0c
> 5. Metrowerks CodeWarrior 5 - 7
>
> All these compilers properly called the destructor of all created objects if the exception is thrown during the operator new [].  I originally guessed that the problem was due to incorrect stack unwinding.

The code shows that.
I also noticed that it worked differently with other compilers.

Jan


March 26, 2002
Thanks for posting the bug, I'll add it to the bug list. -Walter

"SteveTao" <SteveTao_member@pathlink.com> wrote in message news:a7qe95$13ne$1@digitaldaemon.com...
> The code I provided was to demonstrate that if the exception is thrown
during
> the operator new [], the destructor of all created objects must be called.
>
> The code was working correctly with the following compilers:
> 1. Microsoft Visual C++ 6.0 - 7.0
> 2. Borland C++ 5.02 - 5.5.1
> 3. GNU GCC 2.95.0 - 3.04
> 4. Watcom C++ 11.0c
> 5. Metrowerks CodeWarrior 5 - 7
>
> All these compilers properly called the destructor of all created objects
if the
> exception is thrown during the operator new [].  I originally guessed that
the
> problem was due to incorrect stack unwinding.
>
> Steve
>
> In article <3CA0B5E6.271CE29F@smartsoft.cc>, Jan Knepper says...
> >
> >I am not sure if this is stack unwinding or the fact that you throw an exception during a new [] which does not revert the contructions by destructing the constructed elements.
> >
> >Jan
> >
>
>