Title: CS 204 Advance Programming Exception Handling in C
1CS 204 Advance Programming Exception Handling in
C
- Some slides thanks to Yucel Saygin and Hannu
Laine
2Exceptions
- Good program is stable and fault tolerant.
- In a good program, exceptional (error)
situations must be handled. - Exceptions are unusual/unexpected events (not
necessarily erroneous) - They may be detected by either hardware or
software - They may require special processing
- Exception handler is part of the code that
processes an exception - Some examples for exceptions
- EOF is reached while trying to read from a file
- Division by 0 is attempted (result is
meaningless) - Array subscript is out of range
- Bad input
-
3Exception Handling
- In traditional code, the following may be done in
error-prone situations - error values are returned from a function
- new or malloc() returns null for out of memory
- fopen() returns null when the file can not be
opened - a global error condition flag is set
- The programmer is then responsible for checking
these returned values
4Exception Handling
- Example.
- if ((p malloc(sizeof(float)) NULL)
- //handle error
- if ( (f fopen(file.txt, r) ) NULL)
- //handle error
- This kind of error detection
- makes the program logic unclear.
- cannot be used to handle errors in constructors
(because they dont return a value). - user may not check the returned error
- errors must be handled immediately. The
application should decide how to act in error
situations. - Because of these drawbacks a new method to handle
error situations (exceptions) is developed in C.
5More advantages
Exception handling unwinds the stack. It means
that all objects that are allocated from the
stack in a failed block are released and their
destructors are called. Exception handling is
fully object oriented method (it is possible to
use polymorphic exception handling). With
exception handling, it is possible to separate
the code needed fornormal operation and for
exception situations. It is possible to decide
at what level the exception is handled.
6Exception Handling in C
7Basics
- try identifies a code block where exception can
occur - throw causes an exception to be raised (thrown)
- catch identifies a code block where the
exception will be handled (caught) - try
-
-
- throw an exception
-
-
- catch the exception
-
8Basics of Exception Handling
9(No Transcript)
10Exception Handling Sample Code
Simple program to convert entered height (in cm)
into inches cout ltlt Enter height
cin gtgt height try if
(height gt 300) throw height
exceeds maximum if (height lt 0)
throw height below minimum cout
ltlt Inch equivalent ltlt ToInches(height)
catch(const char msg)
cout lt msg ltlt endl
11The fundamentals of exception handling
The normal code is put in a so called try
block. It means that we try to execute code
in the try block. If the system succeeds to run
the code, everything is fine. If or when
something goes wrong when code of try block is
executed, this code throws an exception object
and stops executing the code of try block
further. Another part of the code (the error
handling part) can catch the exception (object)
and make necessary actions needed in that error
situation. The exception object can contain
information about the exception, so that the
error handling part of the program can examine
the reason and make appropriate actions.
12How it works
- When an exception is thrown, the remaining code
in the try block is skipped, just as in the case
of the return statement in a function, and every
object created within the try block is destroyed - The throw object is caught by the catch block
where execution continues - The execution continues with the next statement
after the catch block
- while (ch y ch Y)
-
- cout ltlt Enter height
- cin gtgt height
- try
-
- if (height gt 300)
- throw height exceeds maximum
- if (height lt 0)
- throw height below minimum
- cout ltlt Inch equivalent ltlt
- ToInches(height)
-
- catch(const char msg)
-
- cout lt msg ltlt endl
-
- .....
13How it works
- When no exception is raised in the try block,
then catch block is skipped. - You can throw exceptions anywhere in the try
block - The operand following the throw keyword can be
any expression and the type of the result of the
expression determines the type of the exception
thrown (can be any type - basic type or user
defined class type) - The input type to the catch statement (the type
of the exception object) is defined as in
function declaration
- while (ch y ch Y)
-
- cout ltlt Enter height
- cin gtgt height
- try
-
- if (height gt 300)
- throw height exceeds maximum
- if (height lt 0)
- throw height below minimum
- cout ltlt Inch equivalent ltlt
- ToInches(height)
-
- catch(const char msg)
-
- cout lt msg ltlt endl
-
14Catching Exceptions
- You must supply at least one catch block for a
try block - try
-
- if (Height gt 100)
- throw height exceeds maximum
- if (Height lt 9)
- throw height below minimum
- // do what you want to do with the
height - cout ltlt do you want to continue?
- cin gtgt ch
-
- //no catch blocks here
- NOT ALLOWED!
15Catching Exceptions
- Catch blocks must immediately follow the try
block without any program code between them. - try
-
- if (Height gt 100)
- throw height exceeds maximum
- if (Height lt 9)
- throw height below minimum
- // do what you want to do with the
height - cout ltlt do you want to continue?
- cin gtgt ch
-
- cout ltlt ..... // not allowed
- catch(const char msg)
-
- cout lt msg ltlt endl
-
16Catching Exceptions
- Catch blocks will catch exceptions of the correct
type that occur in the code in the immediately
preceding try block, including the ones thrown by
functions called within the try block. - try
-
- if (Height gt 100)
- throw height exceeds maximum
- if (Height lt 9)
- throw height below minimum
- foo(height)
-
- catch(const char msg)
-
- cout lt msg ltlt endl
-
17Nested tries
- In case of nested try blocks
- if an exception is thrown from within an inner
try block which is not followed by a catch block
with the right type, the catch handlers for the
outer try block will be searched. - If a catch block cannot handle the particular
exception it has caught, it can rethrow the
exception.
18try while (ch y ch Y)
cout ltlt Enter Height cin gtgt
Height try if
(Height gt 300) throw height
exceeds maximum if (Height lt 1)
throw Height //
cout ltlt do you want to continue?
cin gtgt ch
catch(const char msg) cout lt
msg ltlt endl catch(int
BadHeight) cout ltlt BadHeight ltlt
is below minimumltlt endl
- The exception of type const char is caught by
the catch block in the inner try block
- The exception of type int has no catch handler
for exceptions of that type, so the the catch
handler in the outer try block is executed
19Catching exceptions
- If you want to catch any exception that is thrown
in a try block, you specify this as - catch ()
-
- // code to handle any exception
-
- This catch block must appear last if you have
other catch blocks defined for the try block. - Note that in this catch block, you do not know
what type of exception has occured and cannot
reference an object
20Catching Exceptions
main() try throw "error"
catch (int i)
If an exception is not caught by any catch
statement because there is no catch statement
with a matching type, the special function
terminate will be called. This function is
generally defined so that it terminates the
current process immediately showing an "Abnormal
termination" error message.
21Exception Objects and Good Use of Exceptions
22(No Transcript)
23(No Transcript)
24(No Transcript)
25Stack Unwinding Memory Deallocation
26Stack unwinding
If exception is thrown in a try block (in a
function that is called from a try block or in a
function that is called from a function that is
called from a try block and so on), all local
objects allocated from the stack after the try
block was entered are released (go out of scope)
and their destructors are called. This process is
called stack unwinding. This process guaranties
that when we try to recover from an error, there
are no inconsistent data in the stack and try
block can be started again if desired.
27Stack unwinding
Example 1. void main() try A
a f1() void f1() B
b f2() void f2() C c
throw Exception e
If error occurs in the function f2, the
destructors for objects a, b and c are called and
those objects are deleted from the stack. Note
that this would also return dynamically allocated
memory for those objects (a,b,c), through their
destructors.
28Bad example
- try
- int myarr
- myarr new int LARGECLASS
- Process(myarr)
-
- catch ()
-
- //Need to free the heap memory
- //But there is a problem
- cout ltlt e.Report()
-
29Better
- int myarr
- try
- myarr new int LARGECLASS
- Process(myarr)
-
- catch (ImgException e)
-
- //Need to free the heap memory
- delete myarr
- cout ltlt e.Report()
-
30Best
- try
- arraycls myarr
- Init(myarr) //calls myarr new int
LARGECLASS - Process(myarr)
-
- catch (ImgException e)
-
- //Need to free the heap memory
- delete myarr
- cout ltlt e.Report()
-
31Exception Class Hierarchies
32Inheritance for Exception Classes
- We can use inheritance!
- class MathErr //Base class for a hierarchy of
math exceptions - class Overflow public MathErr
- class Underflow public MathErr
- class ZeroDivide public MathErr
- Â
- Now we can catch any of these exceptions
- try // ...
- catch (Overflow) / ... /
- catch (Underflow) / ... /
- catch (MathErr) / ... /
- try can catch various exceptions, distinguishing
them by their class names--better than switch
33Exception Inheritance
Example try ... ... catch
(SpecialExceptionType1 e) ... catch
(SpecialExceptionType2 e) ... catch
(GeneralExceptionType e) ... catch(...)
...
SpecialExceptionType1 and SpecialExceptionType2
are inherited from GeneralExceptionType. SpecialE
xceptionType1 and SpecialExceptionType2 have
their own handling block (catch block). All
other exception inherited from GeneralExceptionTyp
e are handled in common catch block. All other
exceptions (that dont have GeneralExceptionType
as a base) are handled in the last catch block.
34C Exception Classes
35Standard exception classes
C standard defines the following class
hierarchy for exceptions. It is meant to serve
as a starting point so that programmers can
inherit and develop their own exceptions. The
base class for this class hierarchy is exception.
36C Exception Classes
Some functions of the standard C language
library send exceptions that can be captured if
we include them within a try block. These
exceptions are sent with a class derived from
stdexception as type. This class
(stdexception) is defined in the C standard
header file ltexceptiongt and serves as base for
the standard hierarchy of exceptions
include ltiostreamgt include ltexceptiongt using
namespace std main() try char c
new char10 catch (stdexception e)
cout ltlt "Exception " ltlt e.what()
37Standard exception classes
Exception class hierarchy exception
bad_alloc //class bad_alloc public
exception bad_cast bad_typeid logic_er
ror domain_error invalid_argument length_
error out_of_range runtime_error range_err
or overflow_error underflow_error ios_base
failure bad_exception
38Standard exception classes
Exception class hierarchy exception
bad_alloc bad_cast bad_typeid lo
gic_error domain_error invalid_argument l
ength_error out_of_range runtime_error ran
ge_error overflow_error underflow_error io
s_basefailure bad_exception
A logic error indicates an inconsistency in the
internal logic of a program, or a violation of
pre-conditions on the part of client software.
For example, the substr member function of the
standard string class throws an out_of_range
exception if you ask for a substring beginning
past the end of the string. A bad_alloc
exception occurs when heap memory is exhausted.
C will generate a bad_cast exception when a
dynamic_cast to a reference type fails. If you
rethrow an exception from within an unexpected
handler, it gets converted into a bad_exception.
If you attempt to apply the typeid operator to a
null expression, you get a bad_typeid exception.
39Memory allocation errors
- Some build-in operations (global or class
operations) throw an exception when they dont
succeed to complete the asked operation or they
can be asked to do so. - There are three options how memory allocation
errors can be handled - Option 1. Conventional way new returns 0 when
allocation fails - Option 2. Programmer can write his/her own
new_handler - Option 3. New throws an exception (bad_alloc) if
allocation fails.
40(No Transcript)
41Input /output errors
- It is possible to make input stream to throw an
exception when an error flag is set. - This is done with the member function
exceptions. - The parameter is used to indicate what bits
should cause the exception.
For example, the call cin.exceptions(iosfail
iosbad) makes the cin object to throw the
exception iosfailure, if failbit or bad bits
are set in the following input operations. The
exception type is ios_basefailure. If
exception has occurred, we can test the error
flags to find out what error caused the
exception.
42Example for cin.exceptions
- // Read in two floating point numbers and display
the sum. - include ltiostreamgt // stdcout,
stdcin - include ltostreamgt // ltlt, stdendl
- include ltistreamgt // gtgt
- int main()
-
- double a // Number value entered by
the user. - double b // Number value entered by
the user. - stdcin.exceptions( stdios_baseiostate(
-1 ) ) - //We want to use exception handling
- stdcout ltlt "Number A, please? "
- stdcin gtgt a
- stdcout ltlt "Number B, please? "
- stdcin gtgt b
43Out of range errors
If we use vector or strings we can random access
the individual elements in the vector or
characters in the string. If we use indexing
operator operator, the program crashes if index
is out of range. If we use a new member
function (at(i)) for indexing instead or override
the operator, we can throw an out_of_range
exception if index is out of range.
44MFCs Exception Classes
class CException //abstract class public___c
har message___CException( char m ) message
m ___Report() try ___Initialize()___Ru
n()___Shutdown() catch( CException e )
___e.Report()
45Sample Codes
- You should practice to see where the execution
will go if there is an exception of a certain type
46Sample Codes
main() try throw "error"
catch (int i) cout ltlt "caught int
exception"ltlt endl catch (const char
c) cout ltlt "caught"ltlt endl
47Sample Codes
try throw 1 catch(...) cout ltlt
"Caught exception!" ltlt endl
48Stack Class
- include "stackExcp.h"
- void iStackpop( int top_value )
-
- if ( empty() )
- throw popOnEmpty()
- top_value _stack --_top
- cout ltlt "iStackpop() " ltlt top_value ltlt
endl -
- void iStackpush( int value )
-
- cout ltlt "iStackpush( " ltlt value ltlt " )\n"
- if ( full() )
- throw pushOnFull()
- _stack _top value
- // stackExcp.h
- include ltvectorgt
- class iStack
- public
- class popOnEmpty
- .
-
- class pushOnFull
- .
-
- iStack( int capacity )
- _stack( capacity ), _top( 0 )
- bool pop( int top_value )
- bool push( int value )
- bool full()
49Exceptions in Classes
class Vector //detects out of range errors as
exceptions int p int sz public
class Range //an exception class, defined
within class Vector int operator
(int i) if (0lti i lt sz)
return pi //within range, OK
throw Range() //exception--throw a Range
object Â
50Exceptions in Classes more useful/complete
version
class Vector //detects out of range errors as
exceptions public Vector(int n)
size(n) p new intsize class Range
//an exception class, defined within class
Vector int operator (int i) try
if (0lti i lt size)
return pi //within range, OK
else throw Range()
//exception--throw a Range object
catch (Range r) cout ltlt "Out
of range error" private int
p int size Â
51Beauty of exception handling in C
- Instead of terminating the program, you can write
more robust and fault-tolerant code - Instead of returning a value representing error
(e.g., 0 or NULL), we explicitly separate error
handling code form "ordinary" code - We can write more understandable code
52Unexpected Case Handling Methods Summary
- Programmers if statements
- Main approach to dealing with unexpected
situations in simpler programs - E.g. user entered wrong data,...
- Assert()
- Catches situations that SHOULD NOT happen
- E.g. Other programmers in the group told you how
their functions work. You assert this, just to
make sure (so they dont propagate and you wont be
able to find where the bugs are) - Try/Catch
- anything not covered by the above
- Or when there are too many possible problems
making the code long/ugly, gathers all the
handling code in one part - E.g. Disk drive etc. not working
53Good Resources
- http//www.freshsources.com/Except1/ALLISON.HTM