exception handling problem

A

asm23

Hi, everyone, I'm learning <<thinking c++>> volume Two, and testing the
code below.

/////////////////////////////////////////////////////////////////////////////
//: C01:Wrapped.cpp
#include <iostream>
#include <cstddef>
using namespace std;


template<class T, int sz = 1> class PWrap {
T* ptr;
public:
class RangeError {}; // Exception class
PWrap() {
ptr = new T[sz];
cout << "PWrap constructor" << endl;
}
~PWrap() {
delete[] ptr;
cout << "PWrap destructor" << endl;
}
T& operator[](int i) throw(RangeError) {
if(i >= 0 && i < sz) return ptr;
throw RangeError();
}
};

class Cat {
public:
Cat() { cout << "Cat()" << endl; }
~Cat() { cout << "~Cat()" << endl; }
void g() {}
};

class Dog {
public:
void* operator new[](size_t) {
cout << "Allocating a Dog" << endl;
//throw 47; //*******************************NOTE
return 0;
}
void operator delete[](void* p) {
cout << "Deallocating a Dog" << endl;
::delete[](p);
}
};

class UseResources {
PWrap<Cat, 3> cats;
PWrap<Dog> dog;
public:
UseResources() {
cout << "UseResources()" << endl;
}
~UseResources() {
cout << "~UseResources()" << endl;
}
void f() { cats[1].g(); }
};

int main() {
try {
UseResources ur;
} catch(int) {
cout << "inside handler" << endl;
} catch(...) {
cout << "inside catch(...)" << endl;
}
}
/////////////////////////////////////////////////////////////////////////////////
In the UseResources class, It will create *Three cats* and *One dog*,
When I comment the "throw 47" line in the class Dog implementation.
it has the result output:
=================================
Cat()
Cat()
Cat()
PWrap constructor
Allocating a Dog
PWrap constructor
UseResources()
~UseResources()
Deallocating a Dog
PWrap destructor
~Cat()
~Cat()
~Cat()
PWrap destructor
==================================

But When I uncomment the "throw 47" line, the result will be:

=================================
Cat()
Cat()
Cat()
PWrap constructor
Allocating a Dog
~Cat()
~Cat()
~Cat()
PWrap destructor
inside handler
==================================

It seems that an exception happened when we are create the Dog object.

My Question:
When an exception occurred in the allocate a Dog object,
Why was *~UseResources()* not called?
Why was *~Cat()* called?

How does the "exception mechanism" guarantee that the allocated object
will be cleared.

Someone can give this a brief trick? Is it about call stack unwinding?
Thank you very much.
 
A

asm23

Paavo said:
In general, everything which has been constructed will be destructed.
Something is considered constructed when its constructor completes. The
Cats and their PWrap constructors were completed, so they were destructed
as well. The Dog, its PWrap and UseResources constructors were not
completed, so their destructors were not called.

Note that because each your class wraps at most only one potentially
failing resource allocation (a good design!), everything gets cleaned up
automagically, no memory leaks etc.


It's the task for compiler writers, do not worry about this.


Stack unwinding is about different objects in a stack frame, but here the
issue is about subobjects of a complex object, which is slightly
different.

I would say this is more of the class invariants. The destructor is
entitled to expect the object in a good shape, i.e. class invariant
holding. If the constructor did not complete, there is no guarantee that
the class invariant holds, thus the destructor cannot be called.

hth
Paavo

Hi Paavo, Thanks for helping me. The book also suggest that we could use
a wrap class to avoid memory leak in class constructors. But I know,
there are some tricks about the object creating. for example, once an
constructor was executed, the state will be *remembered*, and then if
exception happen after that, there objects in the try block frame will
be recognized and their associated destructor will be called.

I'm not quite understand about the term *class invariants* and *class
invariant holding*. Does this mean the wrap class in my code?

Thanks.
 
A

asm23

Paavo said:
IMO, a good design is such which is exception-safe without any try-catch
blocks. C++ has built-in means (automatic call of destructors) to achieve
this. The only thing which has to be followed is that a single
constructor may not allocate more than 1 raw resource. For example, if
there are two malloc calls in the contructor, then the first may succeed
and the second fail; as the constructor does not complete, the destructor
is not executed and the first resource leaks.

To avoid this, the individual mallocs have to packaged in separate
classes, either a home-made wrapper like in your case, or preferrably in
an existing library class, like std::vector.

See also: http://en.wikipedia.org/wiki/RAII


http://en.wikipedia.org/wiki/Class_invariant

regards
Paavo

Thanks Paavo for the second help.

After carefully reading the RAII article on wikipedia, I gain a lot of
knowledge about RAII. I'm feeling exciting. The exception-safe code is
wonderful.

The main *Idea* I know is "a scoped object is only destroyed if fully
constructed. for example:
foo(){
CMyClass o1;
CMyClass o2;
CMyClass o3;
}
if an exception happened in o2's constructor, since o3 is not
constructed, o3's destructor will never be called in exception handling.


Now, I understand what the term *class invariant* means.
http://www.stanford.edu/~pgbovine/programming-with-rep-invariants.htm

Thanks for helping me, My question is totally solved.
 
A

asm23

Paavo said:
The contribution for which I most want to be remembered:
The C++ destructor and the programming techniques that rely on it.
Yes, Thanks. I read the page.
I think RAII is a big conception we should understand. Through I start
to learned C++ about 4 years ago, I still lack some "big idea and
conception" on this language. I'm writing code like "class and it's
functions" day by day.

Now I think there is more I should to learn in C++. Thanks for bring me
on the right way.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,058
Latest member
QQXCharlot

Latest Threads

Top