Title: Exception Handling
1Exception Handling
Note CIS 601 notes were originally developed by
H. Zhu for NJIT DL Program. The notes were
subsequently revised by M. Deek
2Content
- Exception and Exception Handling
- Structure of exception handling in C
- Exception in Templates
- Group of exceptions
- Scope
3Choices upon an error
- Terminate immediately
- Ignore the error
- Set an error flag, check by the caller
4What 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.
5What 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.
6Common Exceptions
- out-of-bound array subscript
- arithmetic overflow
- divide by zero
- out of memory reference
- invalid function parameters
- etc.
7Benefits of Exception Handling
- improved readability
- easier to modify code
- more robust code
8Without Exception Handling
- include ltiostream.hgt
- include ltstdlib.hgt
- double hmean(double a, double b)
- int main(void)
- double x, y, z
- cout ltlt "Enter two numbers "
- while (cin gtgt x gtgt y)
- z hmean(x,y)
- cout ltlt "Harmonic mean of " ltlt x ltlt " and " ltlt
y ltlt " is " ltlt z ltlt "\n" - cout ltlt "Enter next set of numbers ltq to quitgt
" -
9Without Exception Handling
- cout ltlt "Bye!\n"
- return 0
-
- double hmean(double a, double b)
-
- if (a -b)
-
- cout ltlt "untenable arguments to hmean()"ltltendl
- abort()
-
- return 2.0 a b / (a b)
- //ex11-1.cpp
10(No Transcript)
11With Exception Handling
- include ltiostream.hgt
- include ltstdlib.hgt
- double hmean(double a, double b)
- int main(void)
- double x, y, z
- cout ltlt "Enter two numbers "
- while (cin gtgt x gtgt y)
- try
- z hmean(x,y)
- // end of try block
12With Exception Handling
- catch (const char s) // start of exception
handler -
- cout ltlt s ltlt "\n"
- cout ltlt "Enter a new pair of numbers "
- continue
- // end of handler
- cout ltlt "Harmonic mean of " ltlt x ltlt " and " ltlt
y - ltlt " is " ltlt z ltlt "\n"
- cout ltlt "Enter next set of numbers ltq to quitgt
" -
- cout ltlt "Bye!\n"
- return 0
13With 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(No Transcript)
15Structure of Exception Handling
- try
- statement-list
-
- catch(exception)
- statement-list
-
- catch(exception)
- statement-list
16Procedure 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
17Naming of an Exception
- include ltiostream.hgt
- class ZeroDivide
- const char errmsg
- public
- ZeroDivide()
- errmsg("Error dividing by zero")
- void print() cout ltlt errmsg
-
- float divide(int n1, int n2)
- void main()
- int a, b
- cout ltlt"Input two integers"
18Naming
- cin gtgt a gtgt b
- try float c divide(a,b)
- cout ltlt "a / b " ltlt c ltlt '\n'
-
- catch (ZeroDivide err)
- err.print()
- cout ltlt\nltlt "end of program\n"
-
- float divide(int n1, int n2)
- if (n2 0) throw ZeroDivide()
- return (float) n1 / n2
- //ex11-3.cpp
Results
Input two integers34 0 Error dividing by
zero end of program
19Example
- include ltiostream.hgt
- const unsigned ArraySize 50
- int arrayArraySize
- class RangeError
- void InsertValue(unsigned i, int value)
- if (igtArraySize) throw RangeError()
- arrayi value
-
- void TestTheArray()
- unsigned j
- int anInt
- cout ltlt"Enter a subscript and a value"
20Example
- cin gtgt j gtgt anInt
- InsertValue(j, anInt)
-
- void main()
- try
- TestTheArray()
-
- catch (const RangeError )
- cout ltlt"Range Error in main()!"ltlt endl
-
- //ex11-4.cpp
21(No Transcript)
22Passing Data with Exceptions
- include ltiostream.hgt
- 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 arrayoperator(int i)
- if (igtlower iltupper)
- return (vi-lower)
- throw SubscriptError(i)
- return v
-
- void fun(array a)
- try a100
- catch (arraySubscriptError s)
- cerr ltlt"illegal subscript" ltlts.get() ltlt '\n'
-
-
- void main()
- array ar(20, 40)
- fun (ar)
- //ex-5.cpp
24(No Transcript)
25More than One Exception
- const MAX 500
- class array
- int v, lower, upper
- public
- //
- class SizeError
- array(int l, int u)lower(l), upper(u)
- int size upper-lower1
- if (sizelt0 sizegtMAX)
- throw SizeError()
- else v new intsize
-
If we add another exception SizeError, how is it
done?
26More than One Exception
- void main()
- int l, u
- try
- cout ltlt "Input two bounds for the array"
- cin gtgt lgtgtu
- array ar(l, u)
- fun (ar)
-
- catch (arraySizeError )
- cerr ltlt"illegal size" ltltu - l 1 ltlt '\n'
-
- //ex11-6.cpp
27(No Transcript)
28Unwinding 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.
29Unwinding 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.
30Unwinding
- include ltiostream.hgt
- include ltstring.hgt
- class Test
- class VString
- public
- VString()
- VString(char s)
- VString()cout ltlt"VString Des!"ltltendl
-
- class Transcript
- public
- Transcript()
- throw Test()
-
- Transcript()cout ltlt"Transcript Des!"ltltendl
31Unwinding
- class Student
- VString lastName
- Transcript records
- public
- Student()
- Student()cout ltlt"Student Des!"ltltendl
-
- void main()
- try
- VString collegeName("NJIT")
- Student S
-
- catch (...) cout ltlt "exception!"ltltendl
-
- //ex11-7.cpp
32(No Transcript)
33Multiple 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.
34Example
- include ltstdio.hgt
- include ltiostream.hgt
- include ltfstream.hgt
- class RangeError //Exception
- class InputFileError //Exception
- class 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
35Example
- LongArrayLongArray( unsigned sz )
- size sz
- data new longsize
-
- LongArrayLongArray()
- delete data
- long LongArrayGet( unsigned i ) const
- if( i gt size )
- throw RangeError()
- return datai
36Example
- unsigned ArraySize 50
- void ReadFile( ifstream infile, LongArray L )
- infile.open( "INDATA.TXT" )
- if( !infile )
- throw InputFileError()
-
- void GetArrayElement( const LongArray L )
- unsigned i
- cout ltlt "Enter subscript "
- cin gtgt i
- long n L.Get( i )
-
37Example
- int main()
- try
- ifstream infile
- LongArray L( ArraySize )
- ReadFile( infile, L )
- GetArrayElement( L )
- cout ltlt "Program completed normally.\n"
-
- catch( const RangeError R )
- cout ltlt "Subscript out of range\n"
- catch( const InputFileError F )
- cout ltlt "Unable to open input file\n"
- catch( ... ) cout ltlt "Unknown exception
thrown\n" - return 0
- //except2.cpp
38Results
- Enter subscript 23
- Program completed normally.
- Enter subscript 56
- Subscript out of range
39Ex RangeError Class
- include ltiostream.hgt
- include ltstdlib.hgt
- include ltfstream.hgt
- 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
40Range.h
- include ltiostream.hgt
- include ltstring.hgt
- const unsigned FileNameSize 50
- // Make this gt longest filename on target
system. - class RangeError
- public
- RangeError( const char fname,
- unsigned line,
- unsigned subscr )
-
- strncpy(fileName, fname, FileNameSize)
- lineNumber line
- value subscr
-
41Range.h
- friend ostream operator ltlt( ostream os,
- const RangeError R )
- os ltlt "\nRangeError exception thrown "
- ltlt R.fileName
- ltlt ", line " ltlt R.lineNumber
- ltlt " value " ltlt R.value
- ltlt endl
- return os
-
- private
- char fileNameFileNameSize1
- unsigned lineNumber
- unsigned value
42RangeError
The name of the current source file. __FILE__
expands to a string surrounded by double
quotation marks.
- inline unsigned LongArrayGetSize() const
- return size
- inline void LongArrayPut( unsigned i, long item
) - if( i gt size )
- throw RangeError( __FILE__ ,__LINE__, i )
- datai item
-
- inline long LongArrayGet( unsigned i ) const
- if( i gt size )
- throw RangeError( __FILE__ ,__LINE__, i )
- return datai
The line number in the current source file. The
line number is a decimal constant.
43RangeError
- unsigned GetArraySize()
- unsigned n
- cout ltlt "Number of array elements? "
- cin gtgt n
- return n
-
- void FillArray( LongArray L )
- int i
- try for( i 0 i lt L.GetSize() i )
- L.Put( i, rand() )
-
- catch( const RangeError R )
- cout ltlt R
- throw R
-
44RangeError
- void GetArrayElement( const LongArray L )
- int ok 0
- while( !ok )
- unsigned i
- cout ltlt "Enter an array subscript (0-"ltlt (
L.GetSize()-1 ) ltlt ") " - cin gtgt i
- long n
- try n L.Get( i )
- ok 1
- cout ltlt "Element contains " ltlt n ltlt endl
- catch( const RangeError R )
- cout ltlt R
- cout ltlt "Caught at " ltlt __FILE__ltlt ", line
" ltlt __LINE__ ltlt endl - throw
-
45RangeError
- int main()
-
- try
- LongArray L( GetArraySize() )
- FillArray( L )
- GetArrayElement( L )
-
- catch( ... )
- cout ltlt "Exception caught in main().\n"
- return 1
-
- return 0
- //except3.cpp
46(No Transcript)
47Exception 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 (arraySubscriptError) ...
- ...
49- void fun2(array a)
-
- ...
- try
- ... // use array a
-
- catch (arraySizeError) ...
- ...
50Exception 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.
51No Infinite Loop
- include ltiostream.hgt
- class Over
- void fun()cout ltlt "fun"ltltendl
- throw Over()
-
- void main()
-
- try
- fun()
-
- catch (Over)
- cout ltlt"Over1"ltltendl
- throw Over()
-
- //ex11-8.cpp
52(No Transcript)
53Nesting Exception Handlers
- Exception handlers may be nested.
- Nesting is rarely needed or useful.
- Nesting can make the code difficult to read.
54- include ltiostream.hgt
- class Over
- void fun()cout ltlt "fun"ltltendl
- throw Over()
- void main()
- try fun()
- catch (Over)
- cout ltlt"Over1"ltltendl
- try fun()
- catch (Over)
- cout ltlt"Over2"ltltendl
-
- //ex11-9.cpp
55(No Transcript)
56Exceptions 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- templateltclass TPgt
- class array
- TP v
- int lower, int upper
- public
- class Exception
- ...
58- void fun(arrayltintgt intArr, arrayltfloatgt
fltArr) -
- try
- ...
-
- catch (arrayltintgtException) ...
- catch (arrayltfloatgtException) ...
59A common Exception for a Class Template
- class Exception
- templateltclass TPgt class array
- ...
60- void fun(arrayltintgt intArr, arrayltfloatgt
fltArr) -
- try ...
-
- catch (Exception) ...
-
61Grouping 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 ....
- ...
-
- ...
63Using Inheritance
- class Exception
- class Ex1 public Exception
- class Ex2 public Exception
- class Ex3 public Exception
- ...
64- try
- ...
-
- catch (Ex1)
- ...
-
- catch (Exception)
- ...
- //ex11-11.cpp
65Derived Exceptions
include ltiostream.hgt 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 ltlt op ltlt '(' ltlt opr1
ltlt ',' ltlt opr2 ltlt')' ltltendl
66int add(int x, int y) if( x gt 0 y gt 0 x
gt MAXINT - y x lt 0 y lt 0 x lt 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( )
67Result
void main( ) try f() catch ( Matherr)
cout ltlt"catch another Matherr"ltltendl //e
x11-10.cpp
(200,2)
68Re-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
-
70A Catch for All Exceptions
- void fun()
-
- try g()
- catch (...)
- // do some handling
- throw
-
71The Order of Handlers
- A handler matches if
- it directly refers to the exception thrown.
- it is of a base class of that exception.
72Exception 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.
73Interface Specification
- A function that can throw any exception
- void fun()
- A function that do not throw any exception
- void fun() throw
74Unexpected 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()
76What Should an Exception Handler Do?
- fix the problem and try again
- Re-throw the exception
- Re-throw another exception
- return the needed result
77Scoping 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.
78Resource 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.
79Example
- void fun(char s)
-
- FILE fp fopen(s, r)
- ...
- fclose(f)
80One Approach
-
- File fp fopen(s, r)
- try ...
- catch (...)
- fclose (fp)
- throw
-
- fclose(fp)
81A Better Approach
- class File
- FILE fp
- public
- File(char name, char access)
- fp open(name, access)
- File()
- fclose(fp)
- ...
82Exception 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.
83Readings