1 Exception Handling Lesson #11 Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL...

Preview:

Citation preview

1

Exception Handling

Lesson #11

Note: CIS 601 notes were originally developed by H. Zhu for NJIT DL Program. The notes were subsequently revised by M. Deek

2

Content

Exception and Exception Handling Structure of exception handling in C++ Exception in Templates Group of exceptions Scope

3

Choices upon an error

Terminate immediately Ignore the error Set an error flag, check by the caller

4

What is an Exception?

An error generated by the program at run-time which would normally terminate the execution of the program. Such as, memory exhaustion, subscript

range errors, or division by zero.

5

What is Exception Handling?

A mechanism that allows a program to detect and possibly recover from errors during execution.

The alternative is to terminate the program.

6

Common Exceptions

out-of-bound array subscript arithmetic overflow divide by zero out of memory reference invalid function parameters etc.

7

Benefits of Exception Handling

improved readability easier to modify code more robust code

8

#include <iostream.h>

#include <stdlib.h>

double hmean(double a, double b);

int main(void)

{ double x, y, z;

cout << "Enter two numbers: ";

while (cin >> x >> y)

{ z = hmean(x,y);

cout << "Harmonic mean of " << x << " and " << y << " is " << z << "\n";

cout << "Enter next set of numbers <q to quit>: ";

}

Without Exception Handling

9

cout << "Bye!\n";

return 0;

}

double hmean(double a, double b)

{

if (a == -b)

{

cout << "untenable arguments to hmean()"<<endl;

abort();

}

return 2.0 * a * b / (a + b);

}//ex11-1.cpp

Without Exception Handling

10

11

With Exception Handling

#include <iostream.h>#include <stdlib.h>double hmean(double a, double b);int main(void){ double x, y, z;

cout << "Enter two numbers: ";while (cin >> x >> y){ try {

z = hmean(x,y);} // end of try block

12

With Exception Handlingcatch (const char * s) // start of exception handler{

cout << s << "\n";cout << "Enter a new pair of numbers: ";continue;

} // end of handlercout << "Harmonic mean of " << x << " and " << y

<< " is " << z << "\n";cout << "Enter next set of numbers <q to quit>: ";

}cout << "Bye!\n";return 0;

}

13

With Exception Handling

double hmean(double a, double b)

{

if (a == -b)

throw "bad hmean() arguments: a = -b not allowed";

return 2.0 * a * b / (a + b);

}//ex11-2.cpp

14

15

Structure of Exception Handling

try { statement-list} catch(exception) { statement-list}catch(exception) { statement-list}

16

Procedure for exception handling

try{ func();//1.The program call in try{}} catch(Class anObj){…

//3.Transfer the execution to the program

} func(){ throw exObj;//2.The function throws an exception and transfer

the //execution to the catch block,and assign the exObj //to anObj

}

17

Naming of an Exception#include <iostream.h>class ZeroDivide {

const char* errmsg;public:

ZeroDivide() : errmsg("Error: dividing by zero") { }void print() { cout << errmsg; }

};float divide(int n1, int n2);void main(){ int a, b;

cout <<"Input two integers:";

18

cin >> a >> b;

try { float c = divide(a,b);

cout << "a / b = " << c << '\n';

}

catch (ZeroDivide err)

{ err.print(); }

cout <<“\n”<< "end of program\n";

}

float divide(int n1, int n2)

{ if (n2 == 0) throw ZeroDivide();

return (float) n1 / n2;

}//ex11-3.cpp

Naming

Input two integers:34 0Error: dividing by zeroend of program

Results:

19

Example#include <iostream.h>

const unsigned ArraySize = 50;

int array[ArraySize];

class RangeError{};

void InsertValue(unsigned i, int value)

{ if (i>=ArraySize) throw RangeError();

array[i] = value;

}

void TestTheArray()

{ unsigned j ;

int anInt;

cout <<"Enter a subscript and a value:";

20

Examplecin >> j >> anInt;InsertValue(j, anInt);

}void main(){ try

{ TestTheArray();}catch (const RangeError &){ cout <<"Range Error in main()!"<< endl;}

}//ex11-4.cpp

21

22

Passing Data with Exceptions#include <iostream.h>

class array {int* v, lower, upper;

public:class SubscriptError {

int index;public:

SubscriptError(int i) : index(i) { };int get() { return index; };

};array(int l, int u):lower(l), upper(u){

v = new int [upper-lower +1];};int& operator[](int);~array(){delete [] v;}

};

23

int& array::operator[](int i){ if (i>=lower && i<=upper) return *(v+i-lower);

throw SubscriptError(i);return *v;

};void fun(array& a){ try { a[100]; }

catch (array::SubscriptError s) {cerr <<"illegal subscript:" <<s.get() << '\n';

}}void main(){ array ar(20, 40);

fun (ar);}//ex-5.cpp

24

25

More than One Exceptionconst MAX = 500;

class array {

int* v, lower, upper;

public:

//…

class SizeError {};

array(int l, int u):lower(l), upper(u){

int size = upper-lower+1;

if (size<0 || size>MAX)

throw SizeError();

else { v = new int[size]; }

};

};

If we add another exception SizeError, how is it done?

26

void main(){ int l, u;

try {cout << "Input two bounds for the array:";cin >> l>>u;array ar(l, u);fun (ar);}catch (array::SizeError ){

cerr <<"illegal size:" <<u - l +1 << '\n';}

}//ex11-6.cpp

More than One Exception

27

28

Unwinding the Exception Stack

Stack unwinding: When a program throw an exception, the

destructor is called for each object that was constructed when the program entered the try block.

29

Unwinding the Exception Stack

When an exception is thrown during the construction of a composite object, destructors will be invoked only for those data members that have already been constructed.

30

Unwinding#include <iostream.h>#include <string.h>class Test{};class VString{public:

VString(){ };VString(char *s){ };~VString(){cout <<"VString Des!"<<endl;};

};class Transcript{public:

Transcript(){throw Test();

};~Transcript(){cout <<"Transcript Des!"<<endl;};

};

31

Unwindingclass Student{VString lastName;Transcript records;public:

Student(){};~Student(){cout <<"Student Des!"<<endl;};

};void main(){ try{VString collegeName("NJIT");Student S;} catch (...) {cout << "exception!"<<endl;

}}//ex11-7.cpp

32

33

Multiple Handlers

Most programs performing exception handling have to handle more than one type of exception. A single try block can be followed by multiple handlers(catch), each configured to match a different exception type.

34

Example#include <stdio.h>#include <iostream.h>#include <fstream.h>class RangeError { }; //Exceptionclass InputFileError { }; //Exceptionclass LongArray {public: LongArray( unsigned sz = 0 ); ~LongArray(); long Get( unsigned i ) const;private: long * data; // array of long integers unsigned size; // allocation size};//cis601source/chap8/except/except2.cpp

35

ExampleLongArray::LongArray( unsigned sz ){ size = sz; data = new long[size];}LongArray::~LongArray(){ delete [] data;}long LongArray::Get( unsigned i ) const{ if( i >= size ) throw RangeError(); return data[i];}

36

Exampleunsigned ArraySize = 50;

void ReadFile( ifstream & infile, LongArray & L )

{ infile.open( "INDATA.TXT" );

if( !infile )

throw InputFileError();

}

void GetArrayElement( const LongArray & L )

{ unsigned i;

cout << "Enter subscript: ";

cin >> i;

long n = L.Get( i );

}

37

Exampleint main(){ try { ifstream infile; LongArray L( ArraySize ); ReadFile( infile, L ); GetArrayElement( L ); cout << "Program completed normally.\n"; } catch( const RangeError & R ) { cout << "Subscript out of range\n"; } catch( const InputFileError & F ) { cout << "Unable to open input file\n"; } catch( ... ) { cout << "Unknown exception thrown\n"; } return 0;}//except2.cpp

38

Results

Enter subscript: 23

Program completed normally.

Enter subscript: 56

Subscript out of range

39

Ex: RangeError Class#include <iostream.h>#include <stdlib.h>#include <fstream.h>#include "fstring.h"#include "range.h"class LongArray {public:

LongArray( unsigned sz = 0 ){size = sz; data = new long [sz];}; ~LongArray() {delete [] data;}; unsigned GetSize() const; long Get( unsigned i ) const; void Put( unsigned i, long item );private: long * data; // array of long integers unsigned size; // allocation size}; //cis601source/chap8/except/except3.cpp

40

Range.h#include <iostream.h>

#include <string.h>

const unsigned FileNameSize = 50;

// Make this >= longest filename on target system.

class RangeError {

public:

RangeError( const char * fname,

unsigned line,

unsigned subscr )

{

strncpy(fileName, fname, FileNameSize);

lineNumber = line;

value = subscr;

}

41

Range.h friend ostream & operator <<( ostream & os, const RangeError & R ) { os << "\nRangeError exception thrown: " << R.fileName << ", line " << R.lineNumber << " value = " << R.value << endl; return os; }private: char fileName[FileNameSize+1]; unsigned lineNumber; unsigned value;};

42

RangeErrorinline unsigned LongArray::GetSize() const{ return size;}inline void LongArray::Put( unsigned i, long item ){ if( i >= size ) throw RangeError( __FILE__ ,__LINE__, i ); data[i] = item;}inline long LongArray::Get( unsigned i ) const{ if( i >= size ) throw RangeError( __FILE__ ,__LINE__, i ); return data[i];}

The name of the current source file. __FILE__ expands to a string surrounded by double quotation marks.

The line number in the current source file. The line number is a decimal constant.

43

RangeErrorunsigned GetArraySize(){ unsigned n; cout << "Number of array elements? "; cin >> n; return n;}void FillArray( LongArray & L ){ int i; try { for( i = 0; i < L.GetSize(); i++ ) L.Put( i, rand() ); } catch( const RangeError & R ) { cout << R; throw R; }}

44

RangeErrorvoid GetArrayElement( const LongArray & L ){ int ok = 0; while( !ok ) { unsigned i; cout << "Enter an array subscript (0-"<< ( L.GetSize()-1 ) << "): "; cin >> i; long n; try { n = L.Get( i ); ok = 1; cout << "Element contains " << n << endl; } catch( const RangeError & R ) { cout << R; cout << "Caught at: " << __FILE__<< ", line " << __LINE__ << endl; throw; } }}

45

RangeErrorint main(){ try { LongArray L( GetArraySize() ); FillArray( L ); GetArrayElement( L ); } catch( ... ) { cout << "Exception caught in main().\n"; return 1; } return 0;}//except3.cpp

46

47

Exception with no Catch

If no catch matches the exception generated by the try block, the search continues with the next enclosing try block.

If no catch is found, then error!

48

void fun1(array& a){ ...

try {fun2(a); ...

}catch (array::SubscriptError) { ... }...

}

49

void fun2(array& a){

...try {

... // use array a}catch (array::SizeError) { ... }...

}

50

Exception within an Exception

If the same exception type is raised while handling the exception of a try block, then the new exception is handled by the outer try block.

51

#include <iostream.h>class Over{}; void fun(){cout << "fun"<<endl;throw Over();}void main(){

try {fun();}catch (Over) {

cout <<"Over1"<<endl;throw Over();}

}//ex11-8.cpp

No Infinite Loop

52

53

Nesting Exception Handlers

Exception handlers may be nested. Nesting is rarely needed or useful. Nesting can make the code difficult to

read.

54

#include <iostream.h>

class Over{};

void fun(){cout << "fun"<<endl;

throw Over(); }

void main()

{ try { fun(); }

catch (Over) {

cout <<"Over1"<<endl;

try { fun(); }

catch (Over)

{cout <<"Over2"<<endl; }

}

}//ex11-9.cpp

55

56

Exceptions in Templates

Each class generated can have its own exception class, or

we can have one exception that is common to all the classes generated from the template.

57

template<class TP>

class array {

TP* v;

int lower, int upper;

public:

class Exception { };

...

};

58

void fun(array<int>& intArr, array<float>& fltArr)

{

try {

...

}

catch (array<int>::Exception) { ... }

catch (array<float>::Exception) { ... }

}

59

A common Exception for a Class Template

class Exception { } ;

template<class TP> class array {

...

};

60

void fun(array<int>& intArr, array<float>& fltArr)

{

try { ...

}

catch (Exception) { ...

}

}

61

Grouping of Exceptions

When a set of exceptions are considered to be logically related, it is often best to organize them into a family of exceptions.

62

enum Exception { Ex1, Ex2, Ex3, ... };

try { ... }catch (Exception e) {

switch (e) {case Ex1: ....case Ex2: .......

}...

}

63

Using Inheritance

class Exception { };

class Ex1 : public Exception { };

class Ex2 : public Exception { };

class Ex3 : public Exception { };

...

64

try {

...

}

catch (Ex1) {

...

}

catch (Exception) {

...

}//ex11-11.cpp

65

Derived Exceptions#include <iostream.h>const MAXINT =200;const MININT =0;class Matherr {public:

virtual void debug_print(){};};class int_overflow: public Matherr {public:

char* op;int opr1, opr2;

int_overflow( char* p, int a, int b) { op = p; opr1 = a; opr2 = b; }virtual void debug_print(){ cerr << op << '(' << opr1 <<

',' << opr2 <<')' <<endl; }};

66

int add(int x, int y){

if( x > 0 && y > 0 && x > MAXINT - y|| x < 0 && y < 0 && x < MININT - y)

throw int_overflow("+", x, y);return x + y;

}void f( ){ try {

add(1, 2);add(MAXINT, -2);add(MAXINT, 2);

}catch (Matherr& m) {

m.debug_print( );}

}

67

void main( ){ try {

f();}catch ( Matherr) {cout <<"catch another Matherr"<<endl;

}}//ex11-10.cpp

+(200,2)

Result:

68

Re-throwing an Exception

In some cases when an exception handler is unable to deal with the exception it can re-throw the exception to allow another handler to deal with it.

The original exception is re-thrown.

69

void fun(){

try { ... }catch (Exception) {

if ( ... ) { ... }else throw;

}}

70

A Catch for All Exceptions

void fun(){

try { g(); }catch (...) {

// do some handling throw;

}}

71

The Order of Handlers

A handler matches if: it directly refers to the exception thrown. it is of a base class of that exception.

72

Exception Interface Specification

int fun( ) throw (Ex1, Ex2, Ex3){

...} Specifies that fun may throw

exceptions Ex1, Ex2, and Ex3 and any other exceptions derived from them.

73

Interface Specification

A function that can throw any exception

void fun();

A function that do not throw any exception:

void fun() throw;

74

Unexpected Exceptions

If a function throws an exception not listed or covered by its interface, the function unexpected is called, which results with a call to terminate().

The meaning of unexpected can be redefined using the function set_unexpected().

75

void fun() throw(Ex1, Ex2) { ... }

is equivalent to:

void fun() {

try { ... }

catch (Ex1) { throw; }

catch (Ex2) { throw; }

catch (...) { unexpected(); }

}

76

What Should an Exception Handler Do?

fix the problem and try again Re-throw the exception Re-throw another exception return the needed result

77

Scoping Rules

variables declared within a try block are not accessible outside the block.

variables declared within one catch block may not be accessed from other catch blocks.

variables declared at the beginning of a function may be accessed throughout the try and catch blocks.

78

Resource Acquisition

When a function uses a resource, it is important for the resource to be properly released at the end, even when errors are encountered during the use of the resource.

79

Example

void fun(char* s)

{

FILE* fp = fopen(s, “r”);

...

fclose(f);

}

80

One Approach

{File* fp = fopen(s, “r”);try { ... }catch (...) {

fclose (fp);throw;

}fclose(fp);

}

81

A Better Approach

class File {FILE* fp;

public:File(char* name, char* access){ fp = open(name, access); }~File(){ fclose(fp); }...

};

82

Exception Handling vs. Control Structures

Exception handling is a less structured mechanism than language control structures.

Exception handling is usually less efficient than control mechanisms.

When used for dealing with situations other than errors, it could lead to less understandable code.

83

Readings

Reading: 8.3,8.4

Recommended