SNU OOPSLA Lab. 14. Exception Handling © copyright 2001 SNU OOPSLA Lab.
-
Upload
brian-baldwin -
Category
Documents
-
view
238 -
download
0
Transcript of SNU OOPSLA Lab. 14. Exception Handling © copyright 2001 SNU OOPSLA Lab.
SNUOOPSLA Lab.
14. Exception Handling
© copyright 2001 SNU OOPSLA Lab.
2SNUOOPSLA Lab.C++
Contents
Error Handling Grouping of Exceptions Catching Exceptions Resource Management Exceptions That Are Not Errors Exception Specifications Uncaught Exceptions Standard Exceptions
3SNUOOPSLA Lab.C++
1. Error Handling(1)
Author of a library User of a library
Can detect run-time errorsbut does not in general have any idea what to do about them
Problemoccurs
May know how to cope with such errors but cannot detect them
Notion of Exception
4SNUOOPSLA Lab.C++
1. Error Handling(2)
Traditional techniques terminate the program return a value representing “error” return a legal value and leave the program in an
illegal state call a function supplied to be called in case of “error”
5SNUOOPSLA Lab.C++
Exception handling separates error handling code from “ordinary code”, so program is
more readable more amenable
In exception handling, default response to an error is to terminate the program, so
design process is more important the work involved in getting a program running is
harder
1. Error Handling(3)
6SNUOOPSLA Lab.C++
Alternative views on exceptions to support error handling to handle only synchronous exceptions
ex) array range checks and I/O errors
a non-local control structure based on stack
C++ exception handling mechanisms are provided to report and handle errors and exceptional events
1.1 Alternative views on exceptions
7SNUOOPSLA Lab.C++
Structure of exception handling
class exception_type { ... };
try {
throw exception_object ;
// throw exception
}
catch ( exception_type <name> ) {
// exception handler
// ...
}
Structure of exception handling
8SNUOOPSLA Lab.C++
An exception is an object of some class representing an exceptional occurrence
Code that detects an error throws an object A piece of code express desire to handle an
exception by a catch clause The effect of throw is to unwind the stack until
catch is found Exceptions fall into families
2. Grouping of Exceptions (1)
9SNUOOPSLA Lab.C++
2. Grouping of Exceptions (2)
Exception for a mathematical library
Handle any Matherr without caring precisely which kind it is
class Matherr { };class Overflow : public Matherr{ };class Underflow : public Matherr{ };class Zerodivide : public Matherr{ };
try { // ...}catch (Overflow) {
// handle Overflow or anything derived from Overflow} catch (Matherr) {
// handle any Matherr that is not Overflow}
10SNUOOPSLA Lab.C++
Organizing into hierarchies can be important for robustness of code
If not, be done by exhaustively listing the exceptions
2. Grouping of Exceptions (3)
Matherr
Underflow
ZerodivideOverflow
Withoutgrouping
void g(){
try {// …
}catch (Overflow) { /* … */ }catch (Underflow) { /* … */ }catch(Zerodivide) { /* … */ }}
11SNUOOPSLA Lab.C++
2.1 Derived Exceptions(1) An exception is typically caught by a handler
for its base class rather than by a handler for its exact classclass Matherr {// …virtual void debug_ptint() const { … }
};
class Int _overflow : public Matherr {const char* op;int a1, a2;
public:Int_overflow(const char *p, int a, int b) { … }
virtual void debug_print() const { … }// …
};
void f(){
try {g();
}catch (Matherr m) {
// …}
}
If g() throw Int_overflow? M is Matherr object(Problem)
12SNUOOPSLA Lab.C++
2.1 Derived Exceptions(2)Int add(int s, int y){
if ((x>0 && y>0 && x>INT_MAX-y) || x<0 && y<0 && x<INT_MIN-y))throw Int_overflow(“+”,x,y);
return x+y;}
void f(){
try {int i1 = add(1, 2);int i2 = add(INT_MAX, 2);
}catch (Matherr& m) {
m.debug_print();}
}
Int_overflow::debug_print() will be invoked
13SNUOOPSLA Lab.C++
2.2 Composite Exceptions Not every grouping of exceptions is a tree
structure Often, an exception belongs to two groupsclass Netfile_err : public Network_err, public File_system_err { …};
void f(){
try {// something
catch (Network_err& e) {// …
}}
void g(){
try {// something else
}catch (File_system_err& e) {
// …}
}Network exception
File system exception
14SNUOOPSLA Lab.C++
3. Catching Exceptions(1)
The handler is invoked: if H is the same type as E if H is an unambiguous public base of E if H and E are pointer types and or holds for the
types to which they refer if H is a reference and or holds for the type to
which H refers
void f(){
try {throw E();
}catch(H) {
// when do we get here?}
}
15SNUOOPSLA Lab.C++
An exception is copied when it is thrown, so the handler gets hold of a copy of the original exception
An exception may be copied several times before it is caught
Cannot throw an exception that cannot be copied
3. Catching Exceptions(2)
16SNUOOPSLA Lab.C++
3.1 Re-Throw The handler typically does what can be done
locally and then throws the exception againvoid h(){
try {// code that might throw Math errors
}catch (Matherr) {
if (can_handle_it_completely) {// handle the Matherr
return;}else {
// do what can be done herethrow; // re-throw the exception
}}
} without operand
17SNUOOPSLA Lab.C++
3.2 Catch Every Exception Catch any exception catch(…)
void m(){
try {// something
}catch(...) { //handle every exception
// cleanupthrow;
}}
18SNUOOPSLA Lab.C++
3.2.1 Order of handlers The handlers are tried in order
void f(){
try {// …
}catch (std::ios_base::failure) {
// handle any stream io error}catch (std::exception& e) {
// handle any standard library exception}catch (…) {
//handle any other exception}
}
19SNUOOPSLA Lab.C++
4. Resource Management(1)
The function that acquired a resource release it before returning to its caller
void use_file (const char* fn){
FILE* f=open(fn, “r”);
// use f
fclose(f);}
void use_file (const char* fn){
FILE* f=open(fn, “r”);try {
// use f}
catch (…) {fclose(f);throw;
}fclose(f);}an exception may cause use_file()
to be exited without fcolse() being called
Ver. 1
20SNUOOPSLA Lab.C++
Problem with Ver. 1 is that it is verbose, tedious, and potentially expensive
4. Resource Management(2)
void acquire(){
// acquire resource 1// …// acquire resource n
// use resources
// release resource n// …// release resource 1
}
General form of the problem(Ver. 1)
reverse order
Using constructors and destructors
class File_ptr {FILE* p;
public:File_ptr (const char* a)
{ p = fopen (n, a); }File_ptr (FILE* pp) { p = pp; }~File_ptr() { fclose(p); }
operator FILE* () { return p; }};
void use_file (const char* fn){
File_ptr f(fn, “r”);// use f
}
Ver. 2
21SNUOOPSLA Lab.C++
4.1 Using constructors and destructors(1)
“Resource acquisition is initialization” - the technique for managing resources using local objects
An object is not considered constructed until its constructor has completed
22SNUOOPSLA Lab.C++
4.1 Using constructors and destructors(2)
Memory acquisition
class Y {int* p;void init();
public:Y(int s) { p = new int[s]; init(); }~Y() { delete []p; }// …
};
If an exception is thrown by init(), then the store acquired will not be freed
The destructor will not be called because the object wasn’t completely constructed
class Z {vector<int> p;
void init();public:
Z(int s) : p(s) { init(); }// …
};
The memory used by p is managed by vector
23SNUOOPSLA Lab.C++
4.2 Auto_ptr(1) The standard library provides the template class auto
_ptr Supports the “resource acquisition is initialization” tec
hniqueclass Mess { };
void f(Point p1, Point p2){
auto_ptr<Rectangle> p(new Rectangle(p1, p2));// p points to the rectanglep->retate(45);// …if (in_a_mess) throw Mess();// …
}
Rectangle is deleted whether or not an exception is thrown
24SNUOOPSLA Lab.C++
auto_ptr simplifies the task of writing classes with members that are pointers to objects that need to be deleted when the class objects is destroyed
4.2 Auto_ptr(2)
Class X {auto_ptr<Y> p;// …
public:X() { p = new Y(2); /* … */ };// …
};
25SNUOOPSLA Lab.C++
template<class X> class std::auto_ptr {public:
typedef X element_type;
explicit auto_ptr(X* =0) throw();auto_ptr(const auto_ptr&) throw();template<class Y) auto_ptr(const auto_ptr<Y>&) throw();
auto_ptr& operator=(const auto_ptr&) throw();template<class Y> auto_ptr& operator=(const auto_ptr<Y>&) throw();
~auto_ptr();
X& operator*() const throw();X* operaotr->() const throw();
X* relaease() const throw(); // relinquish ownershipX* get() const throw(); //get ownership back
// … implementation details …};
<memory> standard header
26SNUOOPSLA Lab.C++
After initial construction, an auto_ptr “owns” the object to which it holds a pointer; it is responsible for deleting it
The effect of having more than one auto_ptr “own” an object is undefined; most likely the object will be deleted twice
4.2 Auto_ptr(3)
void g(X* p){
auto_ptr<X>p2(p); // now p2 is responsible for deletionauto_ptr<X>p3(p2); // now p3 is responsible for deletion (and p2 isn’t)
auto_ptr<X>p4(p); // programming error:// now p4 is also responsible for deletion
// …}
27SNUOOPSLA Lab.C++
4.3 Caveat Not all programs need to be resilient against all forms
of failure, and not all resources are critical enough to warrant the effort to protect then using “resource acquisition is initialization,” auto_ptr, and catch(…)
28SNUOOPSLA Lab.C++
4.4.4 Exceptions and New
What happens if X’s constructor throws an exception?
Void f(Arena& a, X* buffer){
X* p1 = new X;X* p2 = new X[10];
X* p3 = new (buffer[10]) X; // place X in buffer (no deallocation needed)X* p4 = new (buffer[11]) X[10];
X* p5 = new(a) X; // allocation from Arena a (deallocate from a)X* p6 = new(a) X[10];
}
29SNUOOPSLA Lab.C++
4.5 Resource Exhaustion(1) What to do when an attempt to acquire a
resource fails Two styles of solutions
resumption : ask some caller to fix the problem and carry on
termination : abandon the computation and return to some caller
In C++, resumption model : function-call mechanism termination model : exception handling model
30SNUOOPSLA Lab.C++
4.5 Resource Exhaustion(2)
void* operator new(size_t size){
for (;;) {if (void* p = malloc(size)) return p; // try to find memoryif (_new_handler == 0) throw bad_alloc(); // no handler: give up_new_handler(); // ask for help
}}
void my_new_handler(){
int no_of_bytes_found = find_some_memory();if (no_of_bytes_found < min_allocation) throw bad_alloc(); //give up
Set_new_handler(&my_new_handler);
Pointer to a function maintained by the standard function set_new_handler
31SNUOOPSLA Lab.C++
4.6 Exceptions in Constructors(2)
Exception handling allows the information that a construction failed to be transmitted out of the constructor
class Vector {public:
class Size { };
enum { max = 32000 };
Vector::Vector(int sz){
if (sz<0 || max<sz) throw Size();// ...
}// …
};
Protect itself from excessive demands on memory
32SNUOOPSLA Lab.C++
4.6 Exceptions in Constructors(2)
Vector* f(int i){
try {Vector* p = new Vector(i);// …return p;
}catch (Vector::Size) {
// deal with size error}
}
33SNUOOPSLA Lab.C++
4.6.1 Exceptions and Member Initialization(1)
What happens if a member initializer throws an exception?
By default, the exception is passed on to whatever invoked the constructor for the member’s class
The constructor itself can catch such exceptions by enclosing the complete function body in a try-block
34SNUOOPSLA Lab.C++
4.6.1 Exceptions and Member Initialization(2)
class X {Vector v;// …
public:X(int);// …
};
X::X(int s)try
:v(s) // initialize v by s{
// …}catch (Vector::Rectagle) { // exceptions thrown for v are caught here
// …}
35SNUOOPSLA Lab.C++
4.7 Exceptions in Destructors
A destructor can be called in one of two ways normal call : as the result of a normal exit from a
scope, a delete, etc. call during exception handling : during stack
unwinding, the exception-handling mechanism exits a scope containing an object with a destructor
If a destructor calls functions that may throw exceptions, it can protect itselfX::~X()
try {f(); // might throw
}catch (…) {
// do something}
36SNUOOPSLA Lab.C++
6. Exception Specifications Specify the set of exceptions that might be
thrown as part of the function declaration
void f(int a) throw (x2, x3);
f() may throw only exceptions x2, x3, and exceptions derived from these types
void f() throw (x2, x3){
// stuff}
void f()try{
// stuff}catch (x2) { throw; }catch (x3) {throw; }catch (…) {
std::unexpected();}
=
The most important advantage is that the function declaration belongs to an interface that is visible to its callers
37SNUOOPSLA Lab.C++
6.1 Checking Exception Specifications(1)
If any declaration of a function has an exception-specification, every declaration of that function must have an exception-specification with exactly the same set of exception types
int f() throw (std::bad_alloc);
int f(){
// …}
error : exception-specification missing
38SNUOOPSLA Lab.C++
A virtual function may be overridden only by a function that has an exception-specification at least as restrictive as its own exception-specification
6.1 Checking Exception Specifications(2)
Class B {public:
virtual void f(); // can throw anythingvirtual void g() throw (X, Y);virtual void h() throw (X);
};
class D : public B {public:
void f() throw (X); //okvoid g() throw (X); //okvoid h() throw (X, Y);
};
error: D::h() is less restrictive than B::h()
39SNUOOPSLA Lab.C++
6.2 Unexpected Exceptions An exception-specification can lead to calls to
unexpected() Such calls can be avoided through careful
organization of exceptions and specification of interfaces
Calls to unexpected() can be intercepted and rendered harmless
40SNUOOPSLA Lab.C++
6.3 Mapping Exceptions The policy of terminating a program upon encountering
an unexpected exception is too Draconian The behavior of unexpected() must be modified Add the standard library exception std::bad_exception
to an exception-specification
Class X{ };class Y{ };
void f() throw (X, std::bad_exception){
// …throw Y();
}
The exception-specification will catch the unacceptable exception Y and throw an exception of type bad_exception instead
41SNUOOPSLA Lab.C++
7.Uncaught Exceptions If an exception is thrown but not caught, the
function std::terminate() will be called The response to an uncaught exception is
determined by an _uncaught_handler set by set_terminate()
Typedef void(*PFV)();PFV set_terminate(PFV);
10. Standard Exceptions(1)
Standard Exceptions (thrown by language)
Name Thrown by Reference
bad_alloc new §6.2.6.2, §19.4.5bad_cast dynamic_cast §15.4.1.1bad_typeid typeid §15.4.4bad_exception exception specification §14.6.3
Standard Exceptions (thrown by standard library)
out_of_range at() §3.7.2, §16.3.3, §20.3.3 bitset<>::operator[]() §17.5.3
invalid_argument bitset constructor §17.5.3.1overflow_error bitset<>::to_ulong() §17.5.3.3ios_base::failure ios_base::clear §21.3.6
43SNUOOPSLA Lab.C++
10. Standard Exceptions(2)
exception
logic_error runtime_error
length_error
domain_error
out_of_range
invalid_argument
bad_alloc
bad_exception
ios_base::failure
bad_cast
range_error
overflow_error
underflow_errorbad_typeid