Professional Documents
Culture Documents
Exceptions
Introduction
Easy to see if proper error checking implemented Harder to read application itself and see how code works Makes clear, robust, fault-tolerant programs C++ removes error handling code from "main line" of program new not allocating memory Out of bounds array subscript Division by zero Invalid function parameters
Exception handling
Common failures
Introduction (II)
So we are not referring to compilation errors. But some error conditions are caused by bugs. However, in our discussion of error handling, we will usually assume that our code is properly written.
Although some error conditions are caused by user mistakes. Suppose we have a function copyFile, which opens a file, reads its contents into a buffer, and writes them to another file. Function copyFile is called in order to read a file on a device that is accessed via a network. Halfway through reading the file, the network goes down. The function is supposed to read the file. This is now impossible. The normal flow of execution cannot handle this. We have an error condition.
An error condition does not mean that the user did something wrong.
Example
Object typically a character string (error message) or class object If exception handler exists, exception caught and handled Otherwise, program terminates
Format
Enclose code that may have an error in try block Follow with one or more catch blocks
If exception occurs and matches parameter in catch block, code in catch block executed If no exception thrown, exception handlers skipped and control resumes after catch blocks throw point - place where exception occurred
2.
3.
Recover from an exception to safely continue execution If full recovery is not possible, display or log error message(s) If the exception cannot be handled locally, clean up local resources and re-raise the exception to propagate it to another handler
Exception-Handling Overview
C++ code
try { code that may raise exception } catch (exceptionType){ code to handle exception }
try block encloses code that may raise exception One or more catch blocks follow
Catch and handle exception, if appropriate Take parameter; if named, can access exception object
Exception-Handling Overview
Throw point
Location in try block where exception occurred If exception handled
If not handled
Function terminates Looks for enclosing catch block
If no exception
Example 1
int main { for(int i=0; i< 5; i++){ try{
if( i< 2)
throw i; cout<<i not thrown-value is<<i<<endl; if (i >3) throw here is another; cout<<end of try block<<endl;
} catch(const int i) { cout<< i caught value is << i<<endl; } catch(const char* pmsg) { cout<<pmsg<< caught<<endl; } cout<<end of the for loop ( after the catch blocks)- i is << i<<endl;
}}
Example 2
class DivideByZeroException
{
Private: const char * message; Public: DivideByZeroException() : message( "attempted to divide by zero" ) { } const char * what() const { return message; }
};
Example 2
double quotient( int numerator, int denominator ) { // throw DivideByZeroException if trying to divide by zero if ( denominator == 0 ) throw DivideByZeroException();
int main() { int number1, number2; double result; cout << "Enter two integers (end-of-file to end): "; while ( cin >> number1 >> number2 ) { try { result = quotient( number1, number2 ); cout << "The quotient is: " << result << endl; } catch ( DivideByZeroException ex ) { // exception handler cout << "Exception occurred: " << ex.what() << '\n'; } cout << "\nEnter two integers (end-of-file to end): "; } cout << endl; return 0; // terminate normally }
Example 2
Example cont.
Enter two integers (end-of-file to end): 100 7 The quotient is: 14.2857 Enter two integers (end-of-file to end): 100 0 Exception occurred: attempted to divide by zero Enter two integers (end-of-file to end): 33 9 The quotient is: 3.66667 Enter two integers (end-of-file to end):
}
main()
{//try block
try{
for (int i = 2; ; i--){ zero_check(i); cout << "Reciprocal: " << 1/i << endl;}
OUTPUT : Reciprocal: 0.5 Reciprocal: 1 Class Zero Constructor Invoked!! DIVIDE BY ZERO -ERROR!!
}
//Handler
Example-4
class DivideByZeroException
{
Private: const char * message; Public: DivideByZeroException() : message( "attempted to divide by zero" ) { } const char * what() const { return message; }
};
Example-4 cont.
if ( denominator == 0 ) throw DivideByZeroException(); catch (DivideByZeroException ex ) {
// exception handler
Throws an exception
Exception objects
Constructor can take a string (to describe exception) Member function what() returns that string
Throwing an Exception
Catching an Exception
Format: catch( exceptionType parameterName){ exception handling code } Caught if argument type matches throw type If not caught then terminate called which (by default) calls abort
This handler catches the exception thrown anywhere in the outer try block as well as uncaught exceptions from the inner try block
Example
int main() { for(int i=0; i<3; i++){ try{ if( i== 0) throw i; try{ if (i== 1) throw i; if (i== 2) throw static_cast<.long>(i); } catch(int i) { cout<< int exp caught inner try << i<<endl; } catch( int i) { cout<< int exp caught outer try << i<<endl; catch(long n) { cout<<long exp caught outer try<< i<<endl; }}
} }
The type of the parameter is a direct or indirect base class of the exception class type, or a reference to a direct or indirect base class of the exception class, ignoring const. Derived class type must appear first and the most base class type last.
Example
class trouble { Private: const char* pMsg; Public: trouble (const char* pstr=there is a problem):pMsg(pstr){} virtual const char* what() const; } const char* trouble::what() const { return pMsg; }
Example
Class moreTrouble: public Trouble { public: moreTrouble(const char* pstr=there is more trouble): trouble(pstr){ }; } Class bigTrouble: public moreTrouble { public: bigTrouble(const char* pstr=Really big trouble): moreTrouble( pstr){ }; }
int main() { Trouble tb; moreTrouble mt; big Trouble b; for (int i=0; i<5; i++) { try{ if (i<2) throw tb; if (i<4) throw mt; else throw b;} Catch(bigTrouble& rt) { cout <<Big trouble object caught<<rt.what()<<endl; } Catch(moreTrouble& rt) { cout <<moreTrouble object caught<<rt.what()<<endl;} Catch(Trouble& rt) { cout <<Trouble object caught<<rt.what()<<endl; } cout<< End of for loop value is <<i<<endl; }
Example
Example
int main() { Trouble tb; moreTrouble mt; big Trouble b; for (int i=0; i<5; i++) { try{ if (i<2) throw tb; if (i<4) throw mt; else throw b;} Catch(Trouble& rt) { cout <<Trouble object caught<<rt.what()<<endl; cout<< End of for loop value is <<i<<endl; } }
Catching an Exception
They are of the same type The catch parameter is a public base class of the thrown object The catch parameter is a base-class pointer/ reference type and the thrown object is a derived-class pointer/ reference type
You do not know what type of exception occurred There is no parameter name - cannot reference the object
If found, control resumes after last catch block If several handlers match thrown object, first one found is executed