exception handling - encsamer/teach/coen244/notes/topic04.… · exception handling: commonly used...
TRANSCRIPT
Exception handlingAishy Amer
Electrical & Computer Engineering Concordia University
Lecture Outline:IntroductionTypes or errors or exceptionsConventional error processingException handling in C++
c© A. Amer Exception handling 1
Introduction
In every code there could be unusual or incorrect states
Examples:no memory is allocated; a file is not empty; division by zero; ...
Many errors will crash a running program
Avoid crushesDo not assume that nothing unusual or incorrect
will happen when you write your code
c© A. Amer Exception handling 2
Introduction
Exception handling: a code for unusual cases, errors,exceptions, ...
Exception handling: commonly used but not always
Exception handling: a C++ technique that transferscontrol and information from a point in a programto another point in a program – called an exception handler
An exception handler is associated with a point previouslypassed by the execution
c© A. Amer Exception handling 3
Introduction
Exceptional situation: division by zero – what to do?either terminate the program ordecide to do something else – but what?
Exception handling proceeds as follows:1. Some code (e.g., library software or your code) provides
a mechanism that signals the unusual situations
Signaling is called throwing an exception2. A special code of your program deals with the exceptional
caseDealing is called handling the exception
c© A. Amer Exception handling 4
Type of errors
new returns null pointerno memory allocation was possible
Out-of-bounds array subscript
Arithmetic overflow
Division by zero
Invalid function parameter
Dereference null pointer
...
c© A. Amer Exception handling 5
Conventional error processing
Assert Function:terminate if the assert parameter evaluates to false
(Evaluates an expression and, when the result is false, prints adiagnostic message and aborts the program)
Ignore the error:
used in temporary/ad-hoc software projects
Abort the program:
used in temporary/ad-hoc software projects
Flag the error:
Software checks flags to handle error
c© A. Amer Exception handling 6
Conventional error processing
Report error:send a message to the program user indicating that an erroroccurred
setjump / longjump:
allows program to jump out of nested function callsback to a routine that can handle the error
Built-in handler routines:For example, set_new_handler
c© A. Amer Exception handling 7
Example without exception handling
// Computes the Donuts-Per-Glasses of milk
// Assume that we always have some milk
void main() {
int donuts, milk;
double dpg; //Donuts-Per-Glasses
cout << "Enter number of donuts and number of glasses of milk:\n";
cin >> donuts; cin >> milk;
dpg = donuts/double(milk);
cout << donuts << " donuts.\n" << milk << " glasses of milk.\n"
<< "You have " << dpg << " donuts for each glass of milk.\n";
}
c© A. Amer Exception handling 8
Example without exception handling
dpg = donuts/double(milk);
we may have exceptional situations:• 1) no milk left (division-by-zero is not defined) or• 2) the number of glasses of milk is negative
(a negative amount of milk is meaningless)
To handle this exception we need to modify our code
c© A. Amer Exception handling 9
Example with exception handling
// Computes donuts per glasses of milk: with Exception Handling
void main() {
int donuts, milk;
double dpg; //Donuts-Per-Glasses
cout << "Enter number of donuts and number of glasses of milk:\n";
cin >> donuts; cin >> milk;
if (milk <= 0) //prevent division by zero or negative number of glasses
// => will handle the exceptional situation
cout << donuts << " donuts, and No Milk!\n";
else {
dpg = donuts/double(milk);
cout << donuts << " donuts.\n" << milk << " glasses of milk.\n"
<< "You have " << dpg << " donuts for each glass of milk.\n";
}
}
c© A. Amer Exception handling 10
Example using standard exception handling
void main() {
int donuts, milk;
double dpg; //Donuts-Per-Glasses
try //****{
cout << "Enter number of donuts and number of glasses of milk:\n";
cin >> donuts; cin >> milk;
if (milk <= 0) throw donuts;
dpg = donuts/double(milk);
cout << donuts << " donuts.\n" << milk << " glasses of milk.\n"
<< "You have " << dpg << " donuts for each glass of milk.\n";
}
catch(int e) //****{
cout << e << " donuts, and No Milk!\n";
}
}
c© A. Amer Exception handling 11
Standard exception handling
The basic procedure: try-throw-catchtry something, if it does not work then throw back the error, ablock of code will catch the error and process
Each catch has to be in the same scope where its try is
try
{
Try_Code
Possibly_Throw_An_Exception
More_Code
} // each try is followed by (at least one) catcher
catch( Type catch-block-parameter )
{
Handle_Exception
}
c© A. Amer Exception handling 12
Standard exception handling
The thrown value is called an exceptionThe execution of a thrown-statement is called throwing anexceptionThe catch-block is called the exception handler
c© A. Amer Exception handling 13
Exception handling: catch statement
The thrown value can be of any typeEx: throw donuts may throw a negative or 0 value to the catcher
The catch-block will receive the thrown value(e in the statement catch(int e))
The catch-block is not a functionThe catch-block parameter• has a name for the thrown value that is caught• has a type to specifies the type of thrown value to catch
c© A. Amer Exception handling 14
Defining exception classes
A throw statement can throw a value of any type – Objects too?
Common practice:define a class whose objects can carry the informationyou want to throw to the catch-block
With an exception class you can have different types
to identify each possible kind of exceptional situation
An exception class is a normal class:It is called exception class because it is used to handleexceptions
c© A. Amer Exception handling 15
Defining exception classes: example
//Computes donuts per glasses of milk: use an exception class
class NoMilk {
public:
NoMilk();
NoMilk(int how_many);
int get_donuts();
private:
int count;
};
NoMilk::NoMilk() {}
NoMilk::NoMilk(int how_many){ count = how_many;}
int NoMilk::get_donuts() { return count; }
c© A. Amer Exception handling 16
Defining exception classes: example
void main() {
int donuts, milk;
double dpg; //Donuts-Per-Glasses
try
{
cout << "Enter number of donuts and number of glasses of milk:\n";
cin >> donuts; cin >> milk;
if (milk <= 0) throw NoMilk(donuts);
dpg = donuts/double(milk);
cout << donuts << " donuts.\n" << milk << " glasses of milk.\n"
<< "You have " << dpg << " donuts for each glass of milk.\n";
}
catch(NoMilk e)
{ cout << e.get_donuts() << " donuts, and No Milk!\n"; }
}
c© A. Amer Exception handling 17
Defining exception classes: comments
At throw NoMilk(donuts);the constructor of the class NoMilk is called
This constructor takes one int argument andcreates an object of the class NoMilk
That object is then "thrown"
c© A. Amer Exception handling 18
Handling multiple exceptions
The thrown value can have different types
the catch-block should handle the different types
When catching multiple exceptions,
the order of the catch-blocks can be important
the catch-block will be tried in the order that they appear inthe programthus, the first one that matches the type of the exceptionthrown is the one that is executed
c© A. Amer Exception handling 19
Handling multiple exceptions
try
{
....
if(condition A) throw "This is a char* exception";
if(condition B) throw 5;
if(condition C) throw DivideByZeroError(); //DivideByZeroError is a ?
}
catch( char* Estring ) { cout << Estring << endl; }
catch( int errNum ) { cout << errNum << endl; }
catch( DivideByZeroError DBZE ) { cout << DBZE.what() << endl; }
If no catch block matches the object thrown, then
terminate() is called defaulting in a call to abort!!!
c© A. Amer Exception handling 20
Special catch-block
A special kind of catch-block that will catch a thrown valueof any type:catch (...) // The three dots must be placed
{
<handle unknown thrown types>
// Example: cout<< "classYY::funcXX(): unknown error\n";
}
This is the most general case, so this catch should beincluded at the end after all other cases
c© A. Amer Exception handling 21
Nested try blocks
Nested try blocks: The closest matching catch block is executedtry
{
try
{
throw 5; //****}
catch(int e)
{ cout << "Inner catch: " << e << endl; }
catch(...)
{ cout << "nested try: unknown error\n"; }
throw 7; //****}// end of outer try
catch(int e) // for each catch there has to be a throw!
{ cout << "Outer catch: "<< e<< endl; }
catch(...)
{ cout<< "outer: unknown error\n"; }
c© A. Amer Exception handling 22
Re-throws
The exception cannot be handled by the catch block? re-thrown ittry
{
if(t==10) throw 5;
}
catch( int errNum )
{ // each catch has to be in the same scope where its try is
cout<<"Inner catch\n";
try
{
if (errNum == 5) { throw; } //Re-throw
else { cout << errNum; }
}// end inner try
catch(int errNum)
{ cout << "Outer Catch Block: "<< errNum << endl; }
catch(...)
{ cout << "Outer Catch Block: unknown error\n"; }
}//end of outer catch
c© A. Amer Exception handling 23
Exception handling: classes
Example:
Compute fraction (numerator/denominator)
Use an inverse function
Define an exception class MSG thathandles the various exceptional situations
Zero denominatorNegative denominatorNumerator zero (?)...
c© A. Amer Exception handling 24
Exception handling: classes
//Listing 18.7 Throwing class objects rather than built-in values
class MSG { //Messages mainly corresponding to exceptions
private:
static char* data [6]; // static: one instance for all obj.
public:
static char* msg(int n) { // public static method
if (n<1 || n > 5) // check index validity
return data[0];
else
return data[n]; // return valid string
}
};
c© A. Amer Exception handling 25
Exception handling: classes
// Before use: initialize the static data: Array of strings
char* MSG::data [] =
{
"\nBad argument to msg()\n",
"\nZero denominator is not allowed\n\n",
"\nNegative denominator: ",
"Enter numerator and positive\n",
"denominator (any letter to quit): ",
"Value of the fraction: "
};
c© A. Amer Exception handling 26
Exception handling: classes
class ZeroDenom { // Define ZeroDenom exception
private:
char *msg; // data to be carried to error handler
public:
ZeroDenom () { // it is called by the throw statement
msg = MSG::msg(1); // the message is the second element of data[]
}
void print () const // it is called by the catch block
{ cout << msg; }
};
c© A. Amer Exception handling 27
Exception handling: classes
class NegativeDenom { // Define NegativeDenom exception
private:
long val; // private data for exception info
char* msg;
public:
NegativeDenom(long value) // conversion constructor
{ val = value; msg = MSG::msg(2); }
char* getMsg() const
{ return msg; }
long getVal() const // public methods to access data
{ return val; }
};
c© A. Amer Exception handling 28
Exception handling: classes
inline void inverse(long value, double& answer) {
answer = (value) ? 1.0/value : DBL_MAX;
if (answer==DBL_MAX)
throw ZeroDenom();
if (value < 0)
throw NegativeDenom(value);
}
inline void fraction (long numer, long denom, double& result) {
inverse(denom, result); // result = 1.0 / denom
result = numer * result; // result = numer/denom
}
c© A. Amer Exception handling 29
Exception handling: classes
//... First initialize the static class data: Array of strings
int main() {
long numer, denom; double ans; // numerator, denominator
cout << MSG::msg(3) << MSG::msg(4); // prompt user for data
cin >> numer >> denom; // enter data
try {
fraction(numer,denom,ans); // compute answer
cout << MSG::msg(5) << ans <<"\n\n"; // valid answer
}
catch (const ZeroDenom& zd) // zero denominator
{ zd.print(); }
catch (const NegativeDenom &nd) // negative value
{ cout << nd.getMsg() << nd.getVal() << "\n\n"; }
catch(...)
{ cout<< "Unkown Throw\n"}
return 0;
}
c© A. Amer Exception handling 30
Exception handling: Why
Many errors, such as divide by zero,will crash a running program
Exception handling allows the program torecognize the error,deal with it (either recover or "safely" exit), andreturn to program execution
It provides an "elegant" way to handle and recover from errors
"Improves program readability and modifiability"it permits easy maintenance of existing code
c© A. Amer Exception handling 31
Exception handling: When
In situations when the system can recover from the errorEx.: out-of-bounds array subscript
In situations where the system cannot recover
Valued information is saved and the system is shut downgracefullyExample: system runs out of RAM from a memory leakExample: breaking a communication network
Use exception handling only when it is not possible to handlethe error locally
c© A. Amer Exception handling 32
Exception handling: Why not?
Exceptions should be used in “exceptional cases” only
Exception handling makes programslarger, slower, and harder (often, much harder) to understand
Exception handlingis less efficient than conventional handlingtakes more time to processreturns the program in a different statewhen the processing is finished
c© A. Amer Exception handling 33