1 / 30

159.234 LECTURE 14

159.234 LECTURE 14. Exception Handling. Textbook p. 309-321. Exception Handling. Exceptions are run-time errors that a program may detect. Examples: Division by 0 Access to an array outside of its bounds Exhaustion of the free store memory. Exception Handling.

Download Presentation

159.234 LECTURE 14

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 159.234LECTURE 14 Exception Handling Textbook p. 309-321

  2. Exception Handling • Exceptions are run-time errors that a program may detect. • Examples: • Division by 0 • Access to an array outside of its bounds • Exhaustion of the free store memory

  3. Exception Handling • 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

  4. Exception Handling Effect: Separate policy from mechanism main f() g() h() Exception thrown by i() and caught by f() i() Routines g(), h(), and i() are removed from the run-time stack and their local variables are destructed.

  5. Using throw We use throwto 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 if (x < 0) throw; // throws a default exception cout << sqrt(x) << endl; } 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. Throwing an exception • When the programmer does not specify an alternative action for the program to take in case an exception (error) occurs then: • the terminate() function is invoked; • this calls abort() which stops the program. • Recall the behaviour of assert() function.

  7. Using try-catch try{ if (d==0) { throw"division by 0"; } cout << (N/d) << endl; } catch (const char* s){// handle exceptions cout<< s; cout << "1 used for divisor instead"; cout << " result = " << (N/1); }

  8. Exception Handling • The tryblock is the part of the program we want to monitor for errors. • If an exception occurs, it is thrown using throw. • The exception is caught--using catch, and processed. • Once an exception has been thrown, • control passes to the catchexpression and • tryblock is terminated. • We sometimes describe the catchclause as a “handler”

  9. How exceptions are handled by catch clauses? • More than one catchcan be associated with a try. • different types of exceptions can be caught (e.g. int, char*, class, etc.) • A try clause will have to be immediately followed by a catchclause.

  10. Catch clauses • void Xhandler(inttest){ • try{ • if (test) { • throwtest; • }else { • throw“Value is zero”; • } • } • catch (inti) { • cout << “Caught One!”; • cout << “Value=” << i << endl; • } • catch (const char*str) { • cout << “Caught a string:”; • cout <<str << endl; • } • }

  11. Catch clauses • intmain(){ • cout << "start\n"; • Xhandler(25); • Xhandler(0); • Xhandler(1); • cout <<“end”; • }

  12. Order of Execution of Catch Clauses Constructor: IntVect::IntVect(int n=100): size(n){ if (n < 0) throw(n); p = new int[size]; if(p == 0) throw(“No memory”); }

  13. Order of Execution of Catch Clauses Overloaded operator[] int &IntVect :: operator[] (inti) { if ((i < 0)||(i >= size)) throw(i); return p[i]; }

  14. Order of Execution of Catch Clauses void g(int n){ try { IntVecta(n); //... } catch(int j) { cerr << “Size Error “ << n << endl; g(10);//retry g with legal size } catch(const char *error) { //do something } catch(...) { //do something } }

  15. Order of Execution of Catch Clauses catch(...) is the syntax for catching everything. A general purpose exception handling routine. The catch handlers have to be listed in an order that means they can all be called. so catch(...) must be at the end of the list.

  16. Order of Execution of Catch Clauses If a catch doesn’t manage to handle the error completely - then it may re-throw the exception: catch(int j) { if (j < 3) return; //to the end of try block else throw; // a throw without an operand passes the error up // to next } // enclosing block. The system catches all exceptions not handled by us, with the function terminate()- which aborts the program.

  17. Exception Specifications We can restrict the type of exceptions that a function can throw. • // This function can only throw ints, chars, • // and doubles. • void Xhandler(int test) throw(int, char, double) { • if(test == 0) throw (test); //with or without parenthesis is ok • if(test == 1) throw 'a'; • if(test == 2) throw 123.23; • }

  18. Exception Specifications Exception handling implies a form of run-time type identification mechanism (RTTI), which may require some increase to code size, data size or both. • 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"; • } • }

  19. #include <iostream> #include <exception> 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 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(char *&errorMsg) { cout << "handler: " << errorMsg << endl; delete PCC; } catch(...) { cout << "last handler: " << endl; delete PCC; } cout << "\nend of main." << endl; return 0; } Unwinding of the stack caused by an exception Exhandling.cpp 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 . . .

  20. CC *PCC = 0; //global pointer to CC 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(char *&errorMsg) { cout << "handler: " << errorMsg << endl; delete PCC; } catch(...) { cout << "last handler: " << endl; delete PCC; } cout << "\nend of main." << endl; return 0; } Unwinding of the stack caused by an exception Exhandling.cpp 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. 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 . . .

  21. CC *PCC = 0; //global pointer to CC 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(char *&errorMsg) { cout << "handler: " << errorMsg << endl; delete PCC; } catch(...) { cout << "last handler: " << endl; delete PCC; } cout << "\nend of main." << endl; return 0; } Unwinding of the stack caused by an exception Exhandling.cpp In unwinding the stack, the program does not destroy staticvariables, static objects, or global variables. They will be destroyed when the program exits. Dynamic objects created with the new operator will have to be explicitly destroyed using delete. Usually, they are deleted within the catch block. 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 . . .

  22. Unwinding of the stack caused by an exception Notice that as soon as any exception is thrown, no further statements are executed within the tryblock. After the codes in the triggered catchclause is executed, control passes immediately to the statement following the last catch block and the program finishes normally.

  23. Unwinding of the stack caused by an exception If an exceptionoccurs 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. When the terminate_handleris 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. 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. #include <iostream> #include <exception> #include <fstream> using namespace std; namespace MyLibrary{ intOPENFAILURE= 1; intOUTOFMEMORY = 2; intCORRUPTFILE = 3; //enum {OPENFAILURE=1, // OUTOFMEMORY = 2,CORRUPTFILE = 3}; char * EmptyFile = "****Warning Empty File****"; char* readHeader( char * filename )throw(int, char*) { char *temp; ifstream ifs( filename ); if ( !ifs )throwOPENFAILURE; const intbufferSize = 1024; temp = new char[bufferSize]; if( temp == NULL )throwOUTOFMEMORY; ifs.getline( temp, bufferSize ); if ( ifs.bad() ){ ifs.close(); delete [] temp; throwCORRUPTFILE; } if( temp[0] == '\0' ) { ifs.close();delete [] temp; throwEmptyFile; } 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{ header = readHeader( filename ); } catch( int ex ) { cout << "Caught exception code " << ex << endl; exit(1); // could decide here to ask again if file name was wrong } 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 ****Warning Empty File**** Enter a filename: non-existentfile.txt Caught exception code 1

  26. Data type issues 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 notenum; Otherwise, the program will fail to handle the exceptions (in gcc).

  27. File Handling • Let’s look at a more complete program for opening a file with exception handling. • File Exception Handling 5.cpp

  28. Design Considerations • Not every C++ program should use exception handling. • Throwing exceptions is slower than function calls. • Use other error handling techniques • ( such as returning an error code) when appropriate. • 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.

  29. Summary An Exceptionis 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 provides a systematic and robust approach to coping with errors that cannot be recovered from locally at the point where they are detected. C++ code can raise an exception by using the throwexpression. 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.

  30. Additional References Technical Report on C++ Performance ISO/IEC TR 18015:2006(E) Mastering Visual C++ http://www.cplusplus.com/reference/iostream/ios/bad.html Next: Inheritance

More Related