Download presentation
Presentation is loading. Please wait.
Published byDeirdre May Modified over 9 years ago
1
1 159.234LECTURE 14 159.234 LECTURE 14 Exception Handling Textbook p. 309-321
2
2 Exceptions Exceptions are run-time errors that a program may detect. Examples: Division by 0 Division by 0 Access to an array outside of its bounds Access to an array outside of its bounds Exhaustion of the free store memory Exhaustion of the free store memory Exception Handling
3
3 assert exit Rather than handling errors with assert - which just stops the program, or exit which also just stops the program, we can handle errors using the following keywords: try, catch and throw Exception Handling
4
4 main f() g() h() i() Effect: Separate policy from mechanism Routines g(), h(), and i() are removed from the run- time stack and their local variables are destructed. Exception thrown by i() and caught by f()
5
5 Using throw throw We use throw to indicate an error: //return the square root of a number entered from the keyboard int main(){ cout << "Enter a number: "; double x; cin >> x; //stop the program if the entered value is less than 0 throw// throws a default exception if (x < 0) throw; // throws a default exception cout << sqrt(x) << endl; } thrown exception Operating Systemabort In this example the thrown exception is caught by the Operating System so it is effectively the same as an abort - it just stops the program.
6
6 When the programmer does not specify an alternative action for the program to take in case an exception (error) occurs then: terminate() the terminate() function is invoked; abort() this calls abort() which stops the program. assert() Recall the behaviour of assert() function. Throwing an exception
7
7 try try{ if (d==0) { throw throw "division by 0"; } cout << (N/d) << endl; } catch// handle exceptions catch (const char* s){// handle exceptions cout << s; cout << " 1 used for divisor instead"; cout << " result = " << (N/1); } Using try-catch
8
8 try The try block is the part of the program we want to monitor for errors. throw If an exception occurs, it is thrown using throw. catch The exception is caught--using catch, and processed. Once an exception has been thrown, catch control passes to the catch expression and try try block is terminated. catch We sometimes describe the catch clause as a “handler” Exception Handling
9
9 catch try More than one catch can be associated with a try. different types (e.g. int, char*, class, etc.) different types of exceptions can be caught (e.g. int, char*, class, etc.) try catch A try clause will have to be immediately followed by a catch clause. How exceptions are handled by catch clauses?
10
10 void Xhandler(int test){ try { if (test) { throw throw test; } else { throw throw “Value is zero”; } int i catch (int i) { cout << “Caught One!”; cout << “Value=” << i << endl; } const char *str catch (const char *str) { cout << “Caught a string:”; cout << str << endl; } Catch clauses
11
11 int main(){ cout << "start\n"; Xhandler(25); 0 Xhandler(0); Xhandler(1); cout <<“end”; } Catch clauses
12
12 IntVect::IntVect(int n=100): size(n){ throw if (n < 0) throw(n); p = new int[size]; throw if(p == 0) throw(“No memory”); } Order of Execution of Catch Clauses Constructor:
13
13 int &IntVect :: operator[] (int i) { throwi if ((i = size)) throw(i); return p[i]; } Order of Execution of Catch Clauses Overloaded operator[]
14
14 g(int n) void g(int n) { try { a IntVect a (n); //... } int j catch(int j) { cerr << “Size Error “ << n << endl; g(10);//retry g with legal size g(10); //retry g with legal size } const char *error catch(const char *error) { //do something } catch(...) { //do something } Order of Execution of Catch Clauses
15
15 catch(...) for catching everything catch(...) is the syntax for catching everything. A general purpose exception handling routine. listed in an order The catch handlers have to be listed in an order that means they can all be called. catch(...)end of the list so catch(...) must be at the end of the list. Order of Execution of Catch Clauses
16
16 re-throw If a catch doesn’t manage to handle the error completely - then it may re-throw the exception: catch catch(int j) { if (j < 3) return; //to the end of try block throw else throw; // a throw without an operand passes the error up // to next } // enclosing block. system catches all exceptions not handled by us terminate() The system catches all exceptions not handled by us, with the function terminate() - which aborts the program. Order of Execution of Catch Clauses
17
17 We can restrict the type of exceptions that a function can throw. // This function can only throw ints, chars, // and doubles. Xhandlerthrow(int, char, double) void Xhandler(int test) throw(int, char, double) { throw//with or without parenthesis is ok if(test == 0) throw (test); //with or without parenthesis is ok throw if(test == 1) throw 'a'; throw if(test == 2) throw 123.23; } Exception Specifications
18
18 int main() { try{ Xhandler(0); } catch(int i) { cout << "Caught int\n"; } catch(char c) { cout << "Caught char\n"; } catch(double d) { cout <<"Caught double\n"; } Exception Specifications Exception handling RTTI Exception handling implies a form of run-time type identification mechanism (RTTI), which may require some increase to code size, data size or both.
19
19 #include using namespace std; class CA{ public: CA() { cout << "CA ctor called." << endl; } ~CA() { cout << "CA dtor called." << endl; } }; class CB{ public: CB() { cout << "CB ctor called." << endl; } ~CB() { cout << "CB dtor called." << endl; } }; class CC{ public: CC() { cout << "CC ctor called." << endl; } ~CC() { cout << "CC dtor called." << endl; } }; CC *PCC = 0; //global pointer to CC func() void func() throw(char *) { cout << "start of func()" << endl; CB B; //instance of CB PCC = new CC; //create an instance throw "exception message"; cout << "you'll never see this" << endl; delete PCC; cout << "end of func()" << endl; } int main() { cout << "beginning of main" << endl; try { CA A; func(); cout << "end of try block." << endl; } catch catch(char *&errorMsg) { cout << "handler: " << errorMsg << endl; delete PCC; } catch(...) { cout << "last handler: " << endl; delete PCC; } cout << "\nend of main." << endl; return 0; } Output: (using Visual C++) beginning of main CA ctor called. start of func() CB ctor called. CC ctor called. CB dtor called. CA dtor called. handler: exception message CC dtor called. end of main. Press any key to continue... Unwinding of the stack caused by an exception Exhandling.cpp
20
20 CC *PCC = 0; //global pointer to CC func() void func() throw(char *) { cout << "start of func()" << endl; CB B; //instance of CB PCC = new CC; //create an instance throw "exception message"; cout << "you'll never see this" << endl; delete PCC; cout << "end of func()" << endl; } int main() { cout << "beginning of main" << endl; try { CA A; func(); cout << "end of try block." << endl; } catch catch(char *&errorMsg) { cout << "handler: " << errorMsg << endl; delete PCC; } catch(...) { cout << "last handler: " << endl; delete PCC; } cout << "\nend of main." << endl; return 0; } Output: (using Visual C++) beginning of main CA ctor called. start of func() CB ctor called. CC ctor called. CB dtor called. CA dtor called. handler: exception message CC dtor called. end of main. Press any key to continue... Unwinding of the stack caused by an exception local objects variables After the throw statement is called, func() is terminated first, destroying all local objects and variables. Next, the try block is also terminated, invoking the destruction of all local objects inside the block. Only then that the matching catch clause is executed. As soon as the catch clause is done, the next statement appearing after the last catch clause is executed. Exhandling.cpp
21
21 CC *PCC = 0; //global pointer to CC func() void func() throw(char *) { cout << "start of func()" << endl; CB B; //instance of CB PCC = new CC; //create an instance throw "exception message"; cout << "you'll never see this" << endl; delete PCC; cout << "end of func()" << endl; } int main() { cout << "beginning of main" << endl; try { CA A; func(); cout << "end of try block." << endl; } catch catch(char *&errorMsg) { cout << "handler: " << errorMsg << endl; delete PCC; } catch(...) { cout << "last handler: " << endl; delete PCC; } cout << "\nend of main." << endl; return 0; } Output: (using Visual C++) beginning of main CA ctor called. start of func() CB ctor called. CC ctor called. CB dtor called. CA dtor called. handler: exception message CC dtor called. end of main. Press any key to continue... Unwinding of the stack caused by an exception In unwinding the stack, the program does not destroy static variables, static objects, or global variables. They will be destroyed when the program exits. new operator delete Dynamic objects created with the new operator will have to be explicitly destroyed using delete. Usually, they are deleted within the catch block. Exhandling.cpp
22
22 thrown try Notice that as soon as any exception is thrown, no further statements are executed within the try block. catch After the codes in the triggered catch clause is executed, control passes immediately to the statement following the last catch block and the program finishes normally. Unwinding of the stack caused by an exception
23
23 exception terminate() If an exception occurs while the catch parameter is being initialised or during the unwinding of the stack, the exception mechanism immediately calls the terminate() function without attempting to find another exception handler. Unwinding of the stack caused by an exception terminate_handler implementation-defined When the terminate_handler is called because no matching exception handler was found, it is implementation-defined whether the stack is unwound and local objects are destroyed. (Technical Report on C++ Performance)
24
24 Exception handling errors Exception handling provides a systematic and robust approach to coping with errors that cannot be recovered from locally at the point where they are detected.
25
25 #include using namespace std; namespace MyLibrary { OPENFAILURE int OPENFAILURE = 1; OUTOFMEMORY int OUTOFMEMORY = 2; CORRUPTFILE int CORRUPTFILE = 3; //enum {OPENFAILURE=1, // OUTOFMEMORY = 2,CORRUPTFILE = 3}; char * EmptyFile = "****Warning Empty File****"; readHeaderthrow char* readHeader( char * filename )throw (int, char*) { char *temp; ifstream ifs( filename ); throw OPENFAILURE if ( !ifs )throw OPENFAILURE; const int bufferSize = 1024; temp = new char[bufferSize]; throw OUTOFMEMORY if( temp == NULL ) throw OUTOFMEMORY; ifs.getline( temp, bufferSize ); if ( ifs.bad() ){ ifs.close(); delete [] temp; throw CORRUPTFILE throw CORRUPTFILE; } if( temp[0] == '\0' ) { ifs.close(); delete [] temp; throw throw EmptyFile; } return temp; } }; // end of namespace definition using namespace MyLibrary; int main(){ char filename[80]; cout << "Enter a filename: "; cin.getline( filename, sizeof(filename) ); char *header; try try { readHeader( filename ); header = readHeader( filename ); } catch catch( int ex ) { cout << "Caught exception code " << ex << endl; exit(1); // could decide here to ask again if file name was wrong } catch catch( char * ex ) { cout << "Caught exception message " << ex << endl; exit(1); } cout << "Header is:" << header << endl; delete [] header; return 0; } Example output (program run 3 separate times): Enter a filename: readme.txt Header is: hello there! Enter a filename: emptyfile.txt Caught exception message Caught exception message ****Warning Empty File**** Enter a filename: non-existentfile.txt Caught exception code Caught exception code 1
26
26 const int OPENFAILURE = 1; const int OUTOFMEMORY = 2; const int CORRUPTFILE = 3; //enum {OPENFAILURE=1,OUTOFMEMORY = 2,CORRUPTFILE = 3}; Use const int or int variables for the exception-specification but not enum; Otherwise, the program will fail to handle the exceptions (in gcc). Data type issues
27
File Handling Let’s look at a more complete program for opening a file with exception handling. File Exception Handling 5.cpp 27
28
28 Not every C++ program should use exception handling. is slower Throwing exceptions is slower than function calls. Use other error handling techniques ( such as returning an error code) when appropriate. to communicate program anomalies libraries Exception handling is used to communicate program anomalies between parts of a program that are developed independently (e.g. libraries). It does allow the user of the library to decide what to do when an error occurs rather than hard coding the decisions into the library. Design Considerations
29
29 Exception An Exception is an interruption in the normal flow of program control in response to an unexpected or abnormal event. Normally, these conditions terminate the user program with system-provided error message. Exception handling Exception handling provides a systematic and robust approach to coping with errors that cannot be recovered from locally at the point where they are detected. throw C++ code can raise an exception by using the throw expression. catch clause The exception is handled by invoking an appropriate handler (catch clause) selected from a list of handlers found at the end of the handler’s try block.Summary
30
Additional References 30 Technical Report on C++ Performance ISO/IEC TR 18015:2006(E) Next: Inheritance Mastering Visual C++ http://www.cplusplus.com/reference/iostream/ios/bad.html
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.