CSC 213 Code Chapter 13, Fall 2007
Notre Dame University–Louaize · Program Design and Data Abstraction II · 3 pages
More CSC 213 files
- Code Chapter 9 · Fall 2007FileView
- Useful File Number Systems · Fall 2007FileView
- Useful File IO Stream · Fall 2007FileView
- Code Chapter 8 · Fall 2007FileView
- Useful File Operator Precedence and Associativity · Fall 2007FileView
- Useful File ASCII Table · Fall 2007FileView
- Code Chapter 7 · Fall 2007FileView
- Code Chapter 14 · Fall 2007FileView
Show the text of this file
Exception Handeling
1
Throwing an Exception
throw indicates that an exception has occurred…
! Usually has one operand of any type…
# The operand can be an object… exception object
# Conditional expression can be thrown…
throw condition ? expression_1 : expression_2
! Code referenced in a try block can throw an
exception…
! Exception caught by closest exception handler…
! Control exits current try block and goes to catch
handler (if it exists)
Exception does not terminate the program…
! However, it terminates the block where the exception
occurred…
Exception Handeling
2
...
try {
// Code to be tried…
throw exception_type;
}
catch (type parameter_name) {
// Code to be executed in case of exception 1…
}
catch (...) {
// Code to be executed for all exception …
}
...
Catching an Exception
Exception handlers are defined in catch blocks…
! Format:
catch( exceptionType parameterName){
EExxcceeppttiioonn hhaannddlliinngg ccooddee......
}
! Caught if argument type matches throw type…
! If not caught then terminate called which (by
default) calls abort…
Catch all exceptions… catch(...[JAN1])
! You do not know what type of exception occurred…
! There is no parameter name, thus cannot reference
an object…
! Not to be placed in front of other catch blocks…
None of the other blocks will ever be executed…
Exception Handeling
3
If no handler matches thrown object
! Searches next enclosing try block…
#
If none found, terminate called…
...
try {
if ( number1 == 0 )
throw 0 ;
try {
if ( number1 < 0 )
throw -1 ;
}
catch ( char * str ) {
cout << "Exception: " << str << endl;
}
}
catch ( int i) {
cout << " Exception: " << i << endl;
}
...
#
If found, control resumes after last catch block…
#
If several handlers match thrown object, first one
found is executed…
Exception Handeling
4
class ABC {
public:
ABC() : baseMsg ("Class Exception...") {}
const char *who() const {return baseMsg;}
private:
const char *baseMsg;
};
...
try {
if ( number1 == 0 )
throw ABC();
}
catch ( ABC obj1 ) {
cout << "Exception occurred: "
<< obj1.who() << endl;
}
...
cccaaatttccchhh pppaaarrraaam
mmeeettteeerrr m
mmaaatttccchhheeesss ttthhhrrrooow
wwnnn ooobbbjjjeeecccttt w
wwhhheeennn:::
! They are of the same type… Exact match required,
nnoo pprroom
moottiioonnss//ccoonnvveerrssiioonnss aalllloowweedd…
...
try {
if ( number1 == 0 )
throw 1.0[JAN2] ;
}
catch ( int i ) {
cout << " Exception: " << i << endl;
}
...
! The catch parameter is a class of the thrown
object…
Exception Handeling
5
class ABase {
public:
ABase() : baseMsg ("Base Exception...") {}
const char *who() const {return baseMsg;}
private:
const char *baseMsg;
};
class ADerived : public Abase {
public:
ADerived() : drvMsg ("Derived Exception...") {}
const char *who() const {return drvMsg;}
private:
const char *drvMsg;
};
! The catch parameter is a base class of the thrown
object…
...
ADerived dObj;
...
try {
if ( number1 == 0 )
throw ADerived();
if ( number1 == 1 )
throw dObj;
}
catch ( ABase[JAN3] bObj) {
cout << "Exception occurred: "
<< bObj.who() << endl;
}
...
Exception Handeling
6
...
ADerived *dPtr=&dObj, &dRef=dObj;
...
try {
if ( number1 == 1 )
throw dPtr;
if ( number1 == 2 )
throw dRef;
}
catch ( ABase *bPtr) {
cout << "Exception 1 occurred: "
<< bPtr->who() << endl;
}
catch ( ABase &bRef) {
cout << "Exception 2 occurred: "
<< bRef.who() << endl;
}
...
...
try {
if ( number1 == 0 )
throw 1.0 ;
}
catch ( ... ) {
cout << " Exception occurred...\n";
}
...
! The catch parameter is a base-class pointer/
reference type and the thrown object is a derived-class
pointer/ reference type…
!
The catch handler is catch( ... )
Exception Handeling
7
catch handler should delete space allocated by new
and close any opened files…
! Resources may have been allocated when exception
thrown…
catch handlers can throw exceptions…
! It can only be processed by outer try blocks…
...
try {
if ( number1 == 0 )
throw 0 ;
try {
if ( number1 < 0 ) throw -1 ;
}
catch ( int i) {
cout << "Exception 1: " << i << endl;
throw "Inner exception...";
}
catch ( char * str ) {
cout << "Exception 2: " << str << endl;
}
}
catch ( int i) {
cout << "Exception 3: " << i << endl;
}
catch ( char * str ) {
cout << "Exception 4: " << str << endl;
}
...
Exception Handeling
8
Rethrowing an Exception
It is possible that the handler that caches the exception
may decide that it cannot process it…
Or it may simply want to release some resources before
letting someone else handle the exception…
The handler can simply rethrow the exception with
Throw ;
Rethrown exception detected by next enclosing try
block…
...
try {
if ( number1 == 0 )
throw 0 ;
try {
if ( number1 < 0 ) throw -1 ;
}
catch ( int i) {
cout << "Exception 1: " << i << endl;
throw;[JAN4]
}
catch ( char * str ) {
cout << "Exception 2: " << str << endl;
}
}
catch ( char * str ) {
cout << "Exception 4: " << str << endl;
}
catch[JAN5] ( int i) {
cout << "Exception 3: " << i << endl;
}
...[JAN6]
Exception Handeling
9
Calls
Calls
Calls
Terminates
Terminates
Terminates
Stack unwinding
Function-call stack unwound when exception thrown and
not caught in a particular scope…
! Tries to catch exception in next outer try/catch
block…
! Function in which exception was not caught
terminates…
#
Local variables destroyed…
#
Control returns to place where function was called…
! If control returns to a try block, attempt made to
catch exception…
#
Otherwise, further unwinds stack…
! If exception not caught, terminate called…
main()
catch();
function1()
function2()
Function3()
throw();
EExxcceeppttiioonn
RRaaiisseedd
EExxcceeppttiioonn
H
Haannddlleedd
Exception Handeling
10
#include <iostream.h>
void function3(int m) {
if (m < 0)
throw "Exception thrown in function 3";
cout << "Function Three\n";
}
void function2(int k) {
function3(k);
cout << "Function Two\n";
}
void function1(int i) {
function2(i);
cout << "Function One\n";
}
void main() {
try {
function1(10);
cout << "------------------" << endl;
function1(-10);
}
catch ( char * str) {
cout << "Exception: " << str << endl;
}
}
Function Three
Function Two
Function One
------------------
Exception: Exception thrown in function 3
Exception Handeling
11
Constructors and Exception Handling
Constructors don't have a return type, thus it's not
possible to use return codes…
So what happens when an error is detected in the
constructor?
$ Partially constructed object or Zombie object
#include <iostream.h>
#include <string.h>
class XYZ {
public:
XYZ(int i=10) {iVal=i;}
private:
int iVal;
};
class ABC {
public:
ABC(char *str) {[JAN7]
msg = new char[strlen(str) +1];
if (msg != 0)
strcpy(msg,str);
}
void sayIt() { cout << msg << endl; }
private:
XYZ x1[J8];
char *msg;
};
void main() {
ABC abc("I Love C++");
abc.sayIt();
}
Exception Handeling
12
Put the object into a "deffect" state by setting an internal
status…
class XYZ {
public:
XYZ(int i=10) {iVal=i;}
private:
int iVal;
};
class ABC {
public:
ABC(char *str) {
status = 0;
// Fully constructed.
msg = new char[strlen(str) +1];
if (msg != 0)
strcpy(msg,str);
else
status = -1; // Partially constructed.
}
int isZombie() {return status;}
private:
XYZ x1;
char *msg;
int status;
};
void main() {
ABC abc("Hello World");
if (abc.isZombie())
cout << "Failed to construct\n";
...
...
}
Exception Handeling
13
Throw an exception from the constructor passing some
information… Destructors are called for automatic
objects…
class XYZ {
public:
XYZ(int i=10) {iVal=i;}
~XYZ[JAN9]() {
cout << "XYZ destructor\n";
}
private:
int iVal;
};
class ABC {
public:
ABC(char *str) {
msg = new char[strlen(str) +1];
if (msg == 0)
throw[JAN10] "No Sapce Left\n";
strcpy(msg,str);
}
private:
XYZ x1;
char *msg;
};
void main() {
try {
ABC abc("Hello World");
...
}
catch (char *exMsg) {
cout << exMsg << endl;
}
}
Exception Handeling
14
class XYZ {
public:
XYZ(int i=10) {iVal=i;}
~XYZ() {
cout << "XYZ destructor\n";
}
private:
int iVal;
};
class ABC {
public:
ABC(char *str) {
msg = new char[strlen(str) +1];
if (msg == 0)
throw this;
strcpy(msg,str);
}
void what() {
cout << "Error: No space left..." << endl;
}
private:
XYZ x1;
char *msg;
};
void main() {
try {
ABC abc("Hello World");
...
}
catch (ABC *obj) {
obj->what();
}
}
Exception Handeling
15
Calls
Calls
Calls
Terminates
Destructors and Exception Handling
The C++ rule is that you must be careful throwing an
exception from a destructor …
During stack unwinding, all the local objects are
destructed...
If one of those destructors throws an exception, it
confuses the C++ runtime system…
! Should it ignore the “last thrown exception” and
continue where it was originally headed? Or vice
versa…
So the C++ language guarantees that it will call
terminate() at this point, and terminate() kills the
process.
main()
catch();
function1()
function2()
Function3()
throw();
EExxcceeppttiioonn
RRaaiisseedd
EExxcceeppttiioonn
N
Noott
H
Haannddlleedd
EExxcceeppttiioonn
RRaaiisseedd bbyy
ddeessttrruuccttoorr
Exception Handeling
16
class XYZ {
public:
XYZ(int i=10) {iVal=i;}
~XYZ() {
cout << "Destructor: " << iVal << endl;
if (iVal == 20)
throw "XYZ Destructor Exception\n";
}
private:
int iVal;
};
void function3() {
XYZ x3(30);
throw "Exception thrown in function 3";
}
void function2() {
XYZ x2(20);
function3();
}
void function1() {
XYZ x1(10);
function2();
}
void main() {
try {
function1();
}
catch ( char * str) {
cout << "Exception: " << str << endl;
}
}