Sie sind auf Seite 1von 55

Exceptions

Exceptions are errors or some peculiar problems other

than logic or syntax errors. Exceptions are runtime anomalies or unusual conditions that a program may encounter while executing. Anomalies includes :
Division by zero

Access to an array outside of its bounds


Running out of memory or disk space

Exception handling allows to manage run-time errors in an

orderly fashion.
Exceptions ar e of 2 kinds
Synchronous exceptions
Out of

range index

Overflow

Asynchronous exceptions
Keyboard

interrupts (events beyond the control of the

program.)
Exception handling is designed to handle only synchronous

exceptions.

Exception Handling Mechanism


Steps for handling an exception
1.Detect the problem (Hit the exception) 2.Inform that an error has occurred (Throw the exception) 3.Receive the error information (Catch the exception) 4.Take corrective actions (Handle the exception

Three keywords for handling exceptions are

-try -catch -throw try:- Program statements that you want to monitor for

exceptions are contained in try statement.


throw:- If an exception occurs within the try block is thrown using throw statement. catch:- Exceptions are caught by catch statement. And contains a exception handler.

The statements that may generate an

exception are placed in a try block.


When an exception is detected, it is

thrown using a throw statement in the try block


Try block is followed by one or more

catch blocks.
A catch block catches the exception

thrown by the throw statement in the

try block

If the data type specified by a catch matches that of the


exception, that that catch statement is executed.

If no exception is thrown in a try block, all catch blocks associated


with that try block are ignored and program execution resumes after the last catch block.

General form of try and catch


try { //statements which detects and throws an exception } catch (dataType1 identifier) { //exception-handling code } ... catch (dataType n identifier) {//exception-handling code }... catch (...) {//exception-handling code }

THROWING AN EXCEPTION
In order for an exception to occur in a try block and be

caught by a catch block, the exception must be thrown in the try block using throw statement. The general syntax to throw an exception is: throw expression;

Handling division by 0 exception


int main() { int dividend, divisor, quotient; try { cout << "Enter the dividend: "; cin >> dividend; cout << \nEnter the divisor: "; cin >> divisor; if (divisor == 0) throw divisor; quotient = dividend / divisor; cout << "Quotient = << quotient; } catch (int x) { cout << "Division by <<x; } return 0; }

Throwing an exception from a function outside the try block


Exception can be thrown from outside the try block as long

as it is thrown by a function i.e. called within try block


The exceptions are thrown by functions that are invoked from

within the try block..


The point at which the throw is executed is called throw point. Once an exception is thrown to catch block ,control cannot return

to the throw point.

Throwing an Exception to be Caught by the Calling Code


void Func3() {
try {
void Func4() { if ( error ) throw ErrType; } Return from thrown exception

Func4();
} catch ( ErrType ) {

Function call

Normal return

}
}

# include <iostream> using namespace std; void divide (int x,int y,int z) { if ( ( x-y) != 0) { int r=z/(x-y); cout<<result = <<r; } else { throw(x-y); } } //end of function

} catch (int i) { cout<<caught the exception; } return 0; }

int main() { try { cout<<we are inside the try block; divide(10,20,30); divide(10,10,20);

Multiple catch statements


// Handle division by zero, division by a negative integer, if (divisor < 0) #include<iostream.h> throw "Negative divisor."; int main() quotient = dividend / divisor; { cout << "Quotient = " << quotient; int dividend, divisor , quotient; } catch (int x) try { { cout << "Division by " << x<< endl; cout << "Enter the dividend: "; } catch (const char * s) cin >> dividend; { cout << \nEnter the divisor: "; cout << s << endl; cin >> divisor; } if (divisor == 0) throw divisor; return 0;

Catch all exceptions


Sometimes it is not possible to determine what type of

exception is going to raise .Then we can't design independent catch for handling it
The catch() handler catches all exceptions, no matter what

type.

#include <iostream.h> void test(int x) { try { if (x== 0) throw x; //int if ( x== -1) throw x; //char if ( x== 1) throw 1.0; //float } catch(. . .) //catch all { cout<<caught an exception \n; } }

int main() { cout<<testing generic catch\n test(-1); test(0); test(1); return 0; }

Catching class types


Exception can be of any type, including class types that we create. #include <iostream> double Result; using namespace std; cout << "enter two numbers\n"; class Calculator{ try { public: cout << "First Number: "; double Operand1; cin >> Calc.Operand1; cout << "Operator: "; double Operand2; cin >> Calc.Operator; char Operator; cout << "Second Number: "; }; cin >> Calc.Operand2; int main() { Calculator Calc;

// Make sure the user typed a valid operator if(Calc.Operator != '+' && Calc.Operator != '-' && Calc.Operator != '*' && Calc.Operator != '/') throw Calc.Operator; // Find out if the denominator is 0 if(Calc.Operator == '/') if(Calc.Operand2 == 0) throw 0; switch(Calc.Operator) { case '+ :Result = Calc.Operand1 + Calc.Operand2; break; case '-: Result = Calc.Operand1 - Calc.Operand2; break;

case '*: Result = Calc.Operand1 * Calc.Operand2; break; case '/: Result = Calc.Operand1 / Calc.Operand2; break; } cout << "\n" << Calc.Operand1 << " " << Calc.Operator << " << Calc.Operand2 << " = " << Result; }//end of switch catch(const char n) { cout << "\nOperation Error: " << n << " is not a valid operator"; } catch(const int p) { cout << "\nBad Operation: Division by " << p << " not allowed"; } return 0; }

Restricting exception (Specifying Exceptions)


You can restrict the type of exceptions that a function can throw This can be done by adding a throw list clause to function

definition The general form of this is shown here: ret-type func-name(arg-list) throw(type-list) { // function body }
The type list specifies the type of exceptions that may be thrown.
Throwing any other type of exception will cause abnormal

program termination.

To prevent a function from throwing any exception, it

can be done by making the type list empty like throw(); //empty list in the function header line.

void test (int x) throw (int,char,double) { if (x== 0) throw x; //char else if (x== 1) throw x; //int else if (x== -1) throw 1.0; //double cout <<End of function block \n ; }

int main() { try { cout<<testing throw restrictions\n; cout<<x== 0\n ; test (0); cout<<x==1 \n; test(1); cout<<x== -1 \n;

test(-1); cout <<x== 2 \n; test(2); } catch( char c) { cout <<caught a character \n; } catch(int m) { cout<<caught an integer \n;} catch (double d) { cout<<caught a double \n; } cout<< end of try catch system \n \n; return 0; }

a try block within a function may throw any type of

exception so long as it is caught within that function. The restriction applies only when throwing an exception outside of the function.

Assertion in c++
Asserts are to catch implementation errors.

assert function is used to ensure that a program terminates

with an appropriate error message indicating the type of error and the program location where the error occurred.
The syntax to use the assert function is:

assert(expression);
expression is any logical expression. If expression evaluates to true, the next statement executes. If

expression evaluates to false, a message is written to the standard error device and terminating the program execution.
assert function is defined in the header file cassert

// Division by zero and the assert function. #include<iostream> #include <cassert> using namespace std; int main() { int dividend, divisor, quotient; cout << " Enter the dividend: "; cin >> dividend; Cout<<\nEnter the divisor: "; cin >> divisor;

assert(divisor != 0); quotient = dividend / divisor; cout << "Quotient = " << quotient<< endl; return0; } Output:
Enter the dividend: 24 Enter the divisor:0 Assertion failed: divisor != 0, file c:\c++\assrt.cpp, line 20

These Asserts are available only for Developer for

debugging and are completely removed from Release version of code You can disable assert statements by using preprocessor directive: #define NDEBUG This preprocessor directive #define NDEBUG must be placed before the directive #include <cassert>.

When to use ASSERTs


use Asserts wherever it is needed to test :

1. Validity of function arguments before using them 2. Validity of a pointer before using it 3. Testing any condition that you think, Must be True i.e. checking the values of a variable at some point in code, checking the expected range at some point etc.

Exception Vs Error Handling


An error is an issue with the code that may cause crashing of

the program or return incorrect results .error can be resolved


only by fixing the program . Exception means irregular situations at runtime .
Older approach of error handling uses return value from

function to determine error occurred or not

The following are the advantage of exception handling over error

handling
Exceptions handling provide an easier, more consistent, and safer

mechanism for error handling


Instead of terminating the program, we can write more robust, fault-

tolerant code
we explicitly separate error handling code from "ordinary" code

Return codes from functions can be ignored. Exceptions cannot be

ignored
exception handling forces calling code to recognize an error condition

and handle it.

Terminate() and unexpected() functions


When the program encounters an uncaught exception, it

calls the built-in terminate(). The terminate( ) and unexpected( ) are functions that call other functions to handle an error. by default terminate( ) calls abort( ), and unexpected( ) calls terminate( ). by default, both functions halt program execution when an exception handling error occurs Both functions defined in exception header file

Setting the Terminate and Unexpected Handlers


you can change the functions that are called by terminate( )

and unexpected( ) using set_terminate( ) and set_unexpected( ) functions defined in exception header file

#include <iostream> #include <exception> using namespace std; void myfunction () { throw 'x; // unhandled exception: } int main () { try { myfunction(); } catch (int) { When exception is thrown it does not cout<< "caught int\n"; find a match hence program is } terminated return 0;}

Set_terminate() example
#include <iostream> #include <exception> using namespace std; void myterminate () { cout << "terminate handler called\n"; abort(); // forces abnormal termination } void myfunction () { throw 'x; // unhandled exception: calls terminate handler }

int main () { set_terminate (myterminate); try { myfunction(); } catch (int) { cout<< "caught int\n"; } return 0; }

Set_unexpected() example
// set_unexpected example #include <iostream> #include <exception> using namespace std; void myunexpected () { cout<< "unexpected called\n"; throw 0; } void myfunction () throw (int) { throw 'x; } int main () { set_unexpected (myunexpected); try { myfunction(); } catch (int) { cout<< "caught int\n"; } return 0; }

Output unexpected called caught int

uncaught_exception( )
This function returns true if an exception has been thrown

but not yet caught. Once caught, the function returns false.
Prototype of uncaught_exception( ) is

bool uncaught_exception( );

STANDARD EXCEPTIONS
C++ defines a hierarchy of standard exceptions that are

thrown at run time when abnormal conditions arise such as when operator new fails. The standard exception classes are derived from std::exception class (defined in the <stdexcept> header). The two main derived classes are logic_error runtime_error,

All the classes derived from exception

contains virtual function what, which return the appropriate error messages.
Exception explanation

exception logic_error runtime_error

The base class for all the exceptions thrown by the C++ Standard library. Derived from exception. Reports program logic errors, which could presumably be detected by inspection. Derived from exception. Reports runtime errors, which can presumably be detected only when the program executes.

Logical error exception classes


Exception explanation

domain_error invalid_argument length_error out_of_range

Function argument is invalid Invalid argument in c++ standard functions Objects length exceeds the maximum allowable length Reference to array element out of range

Runtime error exception classes


Exception explanation

range_error overflow_error underflow_error

Report range errors in internal computations Reports an arithmetic overflow. Reports an arithmetic underflow.

Badexception classes
Exception explanation

bad_alloc bad_exception bad_cast bad_typeid

Thrown by new operator when it cannt allocate memory thrown when an exception doesn't match any catch Thrown for failure in dynamic_cast may be thrown by operator typeid

The iostream exception class ios_base::failure is also derived from exception, but it has no further subclasses.it thrown when error in processing an external file

Example for bad_alloc exception


main() {cout<<Demonstrate memory allocation failure; try {int *arr=new int[1000000]; cout<<memory allocated successfully; } catch(exception & err){ cout<<error:program out of memory \n <<err.what(); } return 0;} Output Demonstrate memory allocation failure error:program out of memory

typeid allows to check the type of an expression: typeid (expression) This operator returns a reference to a constant object of

typeid

type type_info that is defined in the standard header file #include <iostream> #include <typeinfo> using namespace std; int main () { int * a,b; cout << "a is: " << typeid(a).name() << '\n'; cout << "b is: " << typeid(b).name() << '\n'; a is: int * b is: int

Bad_typeid example
#include <iostream> #include <exception> #include <typeinfo> using namespace std; class Test1 { virtual Funct() { };

};

int main () { try { Test1 * var = NULL; typeid (*var); } catch (exception& typevar) { cout<<"Exception: "<<typevar.what()<<endl;

out_of_range
// out_of_range example #include<string> #include<iostream> #include<exception> using namespace std; int main() { try { string s1("hello"); string s2("test"); s1.append(s2,5,2); cout<<s1; }
catch(exception &e) { cout<<"caught"<<e.what(); cout<<"\nType:"<<typeid(e).name(); } return 0;}

File exceptions
#include <iostream> #include <exception> #include<fstream> using namespace std; int main() { ifstream fin1; fin1.exceptions(ios::badbit|ios::failbit); cout<<"testing file open error\n";

try { fin1.open("nofile",ios::in); cout<<"file opened"; Output } Testing fileopen error Exception caught:ios_failbit set catch(exception & e) Type:class std::ios_base::failure { cout << "Exception caught:" ; cout << e.what() ; cout<<"\ntype:"<<typeid(e).name(); } return 0; }

Handling Derived-Class Exceptions


when trying to catch exception types that involve base

and derived classes order of catch statement is important


a catch clause for a base class will also match any class

derived from that base.

if we want to catch exceptions of both a base class type

and a derived class type, put the derived class first in the catch sequence. If you don't do this, the base class catch will also catch all derived classes.

// Catching derived classes. #include <iostream> using namespace std; class B { }; class D: public B { }; int main() { D derived; try { throw derived; }

catch(B b) { cout << "Caught a base class.\n"; } catch(D d) { cout << "This won't execute.\n"; } return 0; }

Rethrowing an exception
A handler may decide to rethrow the exception caught

without processing it, by calling throw, with no exception


When an exception is rethrown, it will not be caught by the

same catch statement or any other catch in that group. Rather

it will be caught by an appropriate catch in the outer


try/catch sequence only

void X() { try { throw "hello"; } catch(const char *) { cout<<"Caught char * inside X()"<<endl; Throw; }

int main() { try Caught char * inside X() Caught char * inside main() { X(); } catch(const char *) { cout<<"Caught char * inside main()"<<endl; } return 0; }

Das könnte Ihnen auch gefallen