CS320 Lecture: Exceptions revised 10/2/97
Need: Handout / Transparency of stack with exception handling
Handout / Transparency: contorted example
I. Motivation
- ----------
A. An important property of software is ROBUSTNESS: the ability to respond
reasonably to anomalous conditions
1. In simple applications, primarily arising from malformed input or
bad input values
2. In embedded systems, includes other problems such as hardware failures,
abnormal events etc.
B. Three general approaches:
1. Defensive programming - test everything first
Ex: don't read directly into an integer variable - read into a
string, then check format, then convert
(Only way to deal with malformed input in standard Pascal)
Ex: test data values for legitimacy before using
Problems:
- Can get very burdensome, lead to code size inflation
- Does not cope well with all kinds of problems (how do you defend
against a hardware failure that occurs just after you've checked
it to be sure it's good!)
2. Use of status flags that programmer can test after performing an
operation
Ex: state of an iostream in C++: if (stream.good()) or if (! stream)
Ex: many standard C library routines set a global variable errno to a
non-zero value if they fail
Ex: most VAX system services and run time library routines return a
status code - odd if successful
Problems:
- Can get very burdensome, lead to code size inflation
- Easy to forget or not want to bother
3. Exception handling mechanism - found in many modern languages:
PL1 - first major language to do this
Modern dialects of LISP
Ada
C++
Java
Each language does this in a somewhat different way, but
the basic idea is to cause an orderly, well-defined interruption in
the flow of program control when an exceptional condition arises
II. C++ Exception handling
-- --- --------- --------
A. A feature added to the language in 1989 after 5 years of work. Not yet
implemented by many C++ compilers.
Ex: gnu c++ 2.3 (which we have been using on Faith) does not;
2.7 (on Linus and newly installed on Faith) does, but only
if you include -fhandle-exceptions on compile command line.
(Exception handling is not turned on by default in gnu c++ 2.7
because the implementation is still brittle.)
To turn on exception handling on faith:
gcc/plus/cc1=-fhandle-exceptions file.cc
B. Not used by older standard libraries such as iostream, which were
designed before this facility was commonly available.
C. Two key ideas:
1. A routine that detects an exceptional condition can THROW an
exception.
2. A routine that anticipates that an exception might occur either in
its own code or that of a routine it calls (directly or indirectly)
can CATCH the exception.
D. Example: Stack template with exceptions built in
HANDOUT + TRANSPARENCY
DEMO
Note:
1. throw statement. throw is a reserved word. throw always
throws something, which can be a value of a standard type or
an object - either explicitly specified or implied
Syntax:
throw expression;
or
throw; // to rethrow a previous exception
2. try statement. try is a reserved word. "Wraps" code that
might cause an exception to be thrown (directly or by a
routine it calls).
Syntax:
try
{
...
}
3. catch statement. catch is a reserved word that introduces an
exception handler. One or more handlers immediately follow a
try block to indicate willingness to catch an exception of a
certain type.
Syntax:
catch (TYPE PARAMETER)
{
...
}
E. Exceptions that are thrown are matched with a handler based on the TYPE
of the exception thrown.
Example: The exceptions thrown by the stack routines are of type char *,
and the handler catches an exception of type char *. Any
other type of thrown object would not be caught by this handler.
1. The C++ runtime maintains a list of outstanding try blocks (blocks that
have not exited). When an exception is thrown, the handler(s) for each
are tried in LIFO order until one is found that handles an exception of
the type thrown, or all have been tried (in which case the program
aborts)
a. Any intervening blocks are exited immediately (without completing
execution) and local objects declared in them are destroyed.
b. When a handler is found, its code is executed, at which point the
try statement is considered to have completed (i.e. the rest of the
try statement after the point where the exception was thrown is not
executed.) In effect, the handler replaces the latter part of the
try statement.
c. The exception that was thrown is bound to the parameter declared in
the catch statement, and its value may be used by the handler.
2. A "catch-all" handler that responds to any exception can be declared by
catch (...). Of course, in such a handler the exception itself is not
accessible, since there is no parameter for it to be bound to.
F. A handler can itself throw an exception, in which case the process of
exception handling begins all over with the next previous try
statement. The exception that is thrown can be a new one, or a
handler can rethrow the same exception by just saying throw ;
Example: Contorted exception demo
HANDOUT + TRANSPARENCY
DEMO
III. Using Exceptions in the ATM problem
--- ----- ---------- -- --- --- -------
A. Where might we use exceptions instead of status codes in the ATM machine
example?
ASK
- CardReader: to report an improperly inserted card
- EnvelopeAcceptor: to report a timeout
- Bank: to report disapproval of a transaction - perhaps two kinds of
exceptions: invalidPIN (can be caught, PIN re-entered, and transaction
retried); rejectedTransaction (transaction as a whole must fail)
B. These exceptions are probably best modelled by Classes, rather than simple
types. (In fact, in industrial C++ programming that is typically the
case).
Thus, we might have:
class InvalidCardException
{
public: InvalidCardException();
};
class EnvelopeTimeoutException
{
public: EnvelopeTimeoutException();
};
class InvalidPINException
{
public: InvalidPINException(Transaction & transaction);
Transaction & transaction();
private: Transaction & _transaction;
}
class RejectedTransactionException
{
public: RejectedTransactionException(const char * reason);
const char * reason();
private: const char * _reason;
}
Note that the first two classes have no data and no method except a
constructor. Everything that one needs to know about these exceptions
is contained in their type - e.g. one could have
throw InvalidCardException();
and
catch(InvalidCardException)
and that would suffice.
The latter two classes do carry additional information in the exception
object that the handler can extract and use.
Copyright ©1998 - Russell C. Bjork