exception handling - city university of new york · csc 330 3 an exception is… an unusual, often...
TRANSCRIPT
1CSC 330
CSC 330 Object-Oriented Programming
Exception HandlingException Handling
2CSC 330
C++ Exception Handling
Topics
• Exception Handling• C++ Exception Handling Basics• Throwing and Catching Exceptions• Constructors, Destructors and Exceptions
3CSC 330
An Exception is…
An unusual, often unpredictable event, detectable by software or hardware, that requires special processing; also, in C++, a variable or class object that represents an exceptional event.
An exception handler is a section of program code that is executed when a particular exception occurs.
4CSC 330
AssertionsAssertions
5CSC 330
Program Segment Example
6CSC 330
When to use assert
▪ Catching the program logic errors. Use assertion statements to catch logic errors. You can set an assertion on a condition that must be true according to your program logic. The assertion only has an effect if a logic error occurs.
▪ Checking the results of an operation. Use assertion statements to check the result of an operation. Assertions are most valuable for testing operations which results are not so obvious from a quickvisual inspection.
▪ Testing the error conditions that supposed to be handled. Use assertions to test for error conditions at a point in your code where errors supposed to be handled.
7CSC 330
Exception Handling Basics
• Exception handling is for situations where the function that detects the error cannot deal with it
• Such a function will throw an exception, and “hope” there is an exception handler to catch it
• There is no guarantee that the exception will be caught
• If it’s not caught the program terminates
8CSC 330
...Exception Handling Basics
• Exceptions are thrown and caught using try and catch blocks
try {...
}catch {
...}
• Code in the try block can throw an exception• The catch blocks contains handlers for the
various exceptions• When an exception is thrown in the try block, the
catch blocks are searched for an appropriate exception handler
9CSC 330
SyntaxSyntax
The try-block:try{compound-statement handler-list
handler-list hereThe throw-expression:throw expression
}{The handler:catch (exception-declaration) compound-statement
exception-declaration:type-specifier-list here
}
10CSC 330
Exception-Handling Overview
• Throw point– Location in try block where exception occurred– If exception handled
» Program skips remainder of try block» Resumes after catch blocks
– If not handled» Function terminates» Looks for enclosing catch block
• If no exception– Program skips catch blocks
11CSC 330
Execution of try-catch
Nostatements throw
an exception
Statement following entire try-catch
statement
Astatement throws
an exception
ExceptionHandler
Statements to deal with exception are executed
Control moves directly to exception handler
12CSC 330
Simple Exception-Handling Example: Divide by Zero
• Keyword throw– Throws an exception
» Use when error occurs– Can throw almost anything (exception object, integer, etc.)
» throw myObject;» throw 5;
• Exception objects– Base class exception ( <exception> )– Constructor can take a string (to describe exception)– Member function what() returns that string
13CSC 330
Creating an error object to throw
#include <iostream>using namespace std;
class DivideByZeroError {public:
DivideByZeroError() : message("Divide by Zero") {}void printMessage() const {cout << message;}
private:const char* message;
};
int main(){DivideByZeroError err;err.printMessage();return 0;
}
Divide by Zero
14CSC 330
Divide Function that throws an exception
#include <iostream>using namespace std;
float quotient(int numerator, int denominator) {if (denominator == 0)
throw DivideByZeroError();return (float) numerator / denominator;
}
int main(){int i = 10, j = 3;cout << quotient(i,j) << “\n”;return 0;
}
3.33333
15CSC 330
Execution Generating an Error (without try block)
#include <iostream.h>
float quotient(int numerator, int denominator) {if (denominator == 0)
throw DivideByZeroError();return (float) numerator / denominator;
}
main(){int i = 10, j = 0;cout << quotient(i,j);return 0;
}
TESTPROG.EXEPROGRAM ABORTED
OK
16CSC 330
Simple Exception-Handling Example: Divide by Zero
• Next example– Handle divide-by-zero errors– Define new exception class
» DivideByZeroException
» Inherit from exception– In division function
» Test denominator» If zero, throw exception (throw object)
– In try block» Attempt to divide» Have enclosing catch block
• Catch DivideByZeroException objects
© 2003 Prentice Hall, Inc.All rights reserved.
Outline
fig13_01.cpp(1 of 3)
1 // Fig. 13.1: fig13_01.cpp2 // A simple exception-handling example that checks for3 // divide-by-zero exceptions.4 #include <iostream>
5 6 using std::cout;7 using std::cin;8 using std::endl;
9 10 #include <exception>
11 12 using std::exception;
13 14 // DivideByZeroException objects should be thrown by functions15 // upon detecting division-by-zero exceptions 16 class DivideByZeroException : public exception { 17 18 public:19 20 // constructor specifies default error message 21 DivideByZeroException::DivideByZeroException() 22 : exception( "attempted to divide by zero" ) {} 23 24 }; // end class DivideByZeroException25
Define new exception class (inherit from exception). Pass a descriptive message to the constructor.
© 2003 Prentice Hall, Inc.All rights reserved.
Outline
fig13_01.cpp(2 of 3)
26 // perform division and throw DivideByZeroException object if 27 // divide-by-zero exception occurs28 double quotient( int numerator, int denominator )29 {30 // throw DivideByZeroException if trying to divide by zero31 if ( denominator == 0 )32 throw DivideByZeroException(); // terminate function
33 34 // return division result35 return static_cast< double >( numerator ) / denominator;
36 37 } // end function quotient38 39 int main()40 {41 int number1; // user-specified numerator42 int number2; // user-specified denominator43 double result; // result of division
44 45 cout << "Enter two integers (end-of-file to end): ";
46
If the denominator is zero, throwa DivideByZeroExceptionobject.
© 2003 Prentice Hall, Inc.All rights reserved.
Outline
fig13_01.cpp(3 of 3)
47 // enable user to enter two integers to divide48 while ( cin >> number1 >> number2 ) {49 50 // try block contains code that might throw exception 51 // and code that should not execute if an exception occurs52 try { 53 result = quotient( number1, number2 ); 54 cout << "The quotient is: " << result << endl; 55 56 } // end try 57 58 // exception handler handles a divide-by-zero exception 59 catch ( DivideByZeroException ÷ByZeroException ) { 60 cout << "Exception occurred: "61 << divideByZeroException.what() << endl; 62 63 } // end catch
64 65 cout << "\nEnter two integers (end-of-file to end): ";
66 67 } // end while
68 69 cout << endl;
70 71 return 0; // terminate normally
72 73 } // end main
Notice the structure of the tryand catch blocks. The catchblock can catch DivideByZeroExceptionobjects, and print an error message. If no exception occurs, the catch block is skipped.
Member function what returns the string describing the exception.
© 2003 Prentice Hall, Inc.All rights reserved.
Outline
fig13_01.cppoutput (1 of 1)
Enter two integers (end-of-file to end): 100 7The quotient is: 14.2857
Enter two integers (end-of-file to end): 100 0Exception occurred: attempted to divide by zero
Enter two integers (end-of-file to end): ^Z
21CSC 330
Executing Code in a try block
int main(){cout << "Enter numerator and denominator: ";int numerator, denominator;cin >> numerator >> denominator;try {
float answer = quotient(numerator, denominator);cout << "\n" << numerator << "/"
<< denominator << " = " << answer;}catch (DivideByZeroError error) { //error handler
cout << "ERROR: ";error.printMessage();cout << endl;return 1; //terminate because of error
}return 0; //terminate normally
}Enter numerator and denominator: 3 4
3/4 = 0.75
22CSC 330
...Executing Code in a try block
main(){cout << "Enter numerator and denominator: ";int numerator, denominator;cin >> numerator >> denominator;try {
float answer = quotient(numerator, denominator);cout << "\n" << numerator << "/"
<< denominator << " = " << answer;}catch (DivideByZeroError error) { //error handler
cout << "ERROR: ";error.printMessage();cout << endl;return 1; //terminate because of error
}return 0; //terminate normally
}
Enter numerator and denominator: 3 0ERROR: Divide by Zero
23CSC 330
Throwing an Exception
• When a program encounters an error it throws an exception using throw anObject
• anObject can be any type of object and is called the “exception object”
• Exception will be caught by the closest exception handler (for the try block from which the exception was thrown) which matches the exception object type
• A temporary copy of the exception object is created and initialized, which in turn initializes the parameter in the exception handler
• The temporary object is destroyed when the exception handler completes execution
24CSC 330
...Throwing an Exception
class DivideByZeroError {public:
DivideByZeroError() : message("Divide by Zero"){cout << "construct: DivByZeroObject\n"; }
~DivideByZeroError(){cout << "delete: DivByZeroObject\n";}
void printMessage() const {cout << message;}private:
const char* message;};
Enter numerator and denominator: 3 0construct: DivByZeroObjectdelete: DivByZeroObjectERROR: Divide by Zerodelete: DivByZeroObjectdelete: DivByZeroObject
25CSC 330
Constructors, Destructors and Exception Handling
• Error in constructor– new fails; cannot allocate memory– Cannot return a value - how to inform user?
» Hope user examines object, notices errors» Set some global variable
– Good alternative: throw an exception» Destructors automatically called for member objects» Called for automatic variables in try block
• Can catch exceptions in destructor
26CSC 330
Executing Code in a try block
main(){cout << "Enter numerator and denominator: ";int numerator, denominator;cin >> numerator >> denominator;try {
float answer = quotient(numerator, denominator);cout << "\n" << numerator << "/"
<< denominator << " = " << answer;}catch (DivideByZeroError error) { //error handler
cout << "ERROR: ";error.printMessage();cout << endl;return 1; //terminate because of error
}return 0;
}Enter numerator and denominator: 3 0construct: DivByZeroObjectdelete: DivByZeroObjectERROR: Divide by Zerodelete: DivByZeroObjectdelete: DivByZeroObject
27CSC 330
…Throwing an Exception
• Control exits the current try block and goes to appropriate catch handler
• The try blocks or functions which throw the exception can be deeply nested
• An exception can be thrown by code indirectly referenced from within a try block
• An exception terminates the block in which the exception occurred, and may cause program termination
28CSC 330
Catching an Exception
• Exception handlers are contained within catchblocks
catch(exception_object) { //exception handler code}
• Catch handler specifies the type of object that it catches
• Exceptions which are not caught will cause program termination, by invoking function terminate, which in turn invokes abort
29CSC 330
...Catching an Exception
• Specifying only the exception type is allowed, no object is passed, the type is simply used to select the appropriate handler
catch(exception_type) { //exception handler code}
• Specifying ellipses catches all exceptions
catch(...) { //exception handler code}
30CSC 330
Unnamed Exception Handlers -only type specified
try {float answer = quotient(numerator, denominator);cout << "\n";cout << numerator << "/"
<< denominator << " = " << answer;}catch (DivideByZeroError) { //type only error handler
cout << "ERROR: DIVIDE_BY_ZERO\n";return 1; //terminate because of error
}
Enter numerator and denominator: 3 0construct: DivByZeroObjectdelete: DivByZeroObjectERROR: DIVIDE_BY_ZEROdelete: DivByZeroObjectdelete: DivByZeroObject
31CSC 330
Catching all Exceptions
try {float answer = quotient(numerator, denominator);cout << "\n";cout << numerator << "/"
<< denominator << " = " << answer;}catch (...) { //error handler
cout << "ERROR: ERROR_IN_PROGRAM\n";return 1; //terminate because of error
}
Enter numerator and denominator: 3 0construct: DivByZeroObjectdelete: DivByZeroObjectERROR: ERROR_IN_PROGRAMdelete: DivByZeroObjectOne fewer
destructorsran
32CSC 330
... Throwing ints, doubles, etc
main(){int n = 5;double x = 5.0;try {cout << n << " factorial is " << factorial(n) <<"\n";}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 1; //terminate because of error
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}
return 0;} 5 factorial is 120
33CSC 330
... Throwing ints, doubles, etc
main(){int n = -5;double x = 5.0;try {cout << n << " factorial is " << factorial(n) <<"\n";}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 1; //terminate because of error
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}
return 0;}
ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO
34CSC 330
... Throwing ints, doubles, etc
main(){int n = -5;double x = 5.0;try {cout << x << " factorial is " << factorial(x) <<"\n";}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 1; //terminate because of error
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}
return 0;}
ERROR Double = 5
...ARGUMENT CANNOT BE TYPE double
35CSC 330
Throwing from Conditional Expressions
main(){int n = 5;double x = 5.0;try {n < 0 ? throw int(n) : cout << factorial(n);}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 1; //terminate because of error
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}
return 0; //terminate normally}
120
36CSC 330
...Throwing from Conditional Expressions
main(){int n = -5;double x = 5.0;try {n < 0 ? throw int(n) : cout << factorial(n);}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 1; //terminate because of error
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}
return 0; }
ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO
37CSC 330
...Throwing from Conditional Expressions
main(){int n = -5;double x = 5.0;try {n < 0 ? throw int(n) : throw double(x);}catch ... ERROR INTEGER = -5
...INT MUST BE GREATER THAN ZERO
ERROR Double = 5...ARGUMENT CANNOT BE TYPE double
main(){int n = 5;double x = 5.0;try {n < 0 ? throw int(n) : throw double(x);}catch ...
38CSC 330
...Continuing After an Exception
main(){int n = -5;double x = 5.0;try {cout << n << " factorial is " << factorial(n) <<"\n";}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 1; //terminate because of an error
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}cout << "\n...processing continues...\n";return 0; //terminate normally
}
39CSC 330
Continuing After an Exception
main(){int n = -5;double x = 5.0;try {cout << n << " factorial is " << factorial(n) <<"\n";}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 1; //terminate because of an error
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}cout << "\n...processing continues...\n";return 0; //terminate normally
} ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO
40CSC 330
...Continuing After an Exception
main(){int n = -5;double x = 5.0;try {cout << n << " factorial is " << factorial(n) <<"\n";}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";return 0; //return indicating normal termination
}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}cout << "\n...processing continues...\n";return 0; //terminate normally
} ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO
Same Result
41CSC 330
...Continuing After an Exception (No Return Specified)
main(){int n = -5;double x = 5.0;try {cout << n << " factorial is " << factorial(n) <<"\n";}catch (int error) { //error handler
cout << "\nERROR INTEGER = " << error << "\n";if (error < 0)
cout << "...INT MUST BE GREATER THAN ZERO\n";}catch (double error) { //error handler
cout << "\nERROR Double = " << error << "\n";cout << "\n...ARGUMENT CANNOT BE TYPE double\n";return 1; //terminate because of error
}cout << "\n...processing continues...\n";return 0; //terminate normally
}
ERROR INTEGER = -5...INT MUST BE GREATER THAN ZERO
...processing continues...
42CSC 330
Example
//mismatch type, throw integer type //catch the double type...#include <iostream.h>
void Funct(); int main() {
try { Funct(); }
catch(double) { cerr<<"caught a double
type..."<<endl; } return 0;
} void Funct()
{ //3 is not a double but intthrow 3;
}
Output:
Change the following statement throw 3; to throw 4.123;
Output:
43CSC 330
Processing Unexpected Exceptions
unexpected()
set_unexpected()
terminate()set_terminate()
abort() exit
44CSC 330
Standard Exception HierarchiesStandard Exception Hierarchies
45CSC 330
Standard ExceptionsStandard Exceptions
• The C++ exception class serves as the base class for all exceptions thrown by certain expressions and by the Standard C++ Library.
46CSC 330
47CSC 330