- the error problem
- what happens if there's an error in a constructor
- what happens if there's an error in an overloaded operator
- the error pass-along problem
- out-of-band errors - exceptions
- not propagated along parameters, return values, or globals -
constructors and operators
- can be ignored by intermediate code - pass-along
- exception basics
- the call stack
- the top of the call stack can throw an exception
- a procedure in the call stack can catch an exception
- the procedure closest to the top wanting the exception gets it
- the intervening processes are unwound - the catching process is the new
call-stack top
- the throwing and intervening processes are terminated immediately
- exception problems
- intervening processes have no chance to clean up
- coordinated exceptions among independent modules requires work
- basic exception mechanisms -
throw
, catch
, and try
-
throw
expr throws the value expr as an exception
- like
return
in syntax and semantics
- expr can be a value of any type
-
catch (
type-spec [ name ] ) {
body
}
- catches a thrown exception
- with no name, the actual exception is unknown
- exception types must match exactly - with no conversions but with
polymorphism
- the ellipsis
catch(. . .) { }
catches any exception
- when caught, the body is executed with name (if defined) as
a local variable.
-
try {
body }
catch-stmt . . .
- execute the code in body - fall off the end with no exception
- jump from body to the catch-stmts on exception - a normal
scope exit; destructors are called
- search for a matching catch-stmt in order
- an exception is considered handled as soon as a match is found
- after executing the associated
catch
body, continue after
the try
- if no catch-stmt matches, terminate the current procedure and
continue up the stack
- exception problems
- the scope of the
try
is not the scope of a catch
- exception refinements - it gets confusing
- an exception not handled by
main()
causes termination
- an exception thrown in a
catch
body is like any other
exception
- exceptions raised in destructors cause immediate termination - no stack
unwinding
- exception mechanism refinements
- exception class values
-
<exception>
defines the virtual class exception
- defines
char * exception::what(void) const
-
<stdexcept>
defines some derived exceptions -
runtime_error
and logic_error
- a
catch
handler can rethrow an exception using throw
- a procedure can list the exceptions it throws with a
throw
clause
-
throw (
ex1, ex2, . . . )
- follows the procedure's formal parameter list
- only the listed exceptions can be thrown from the procedure - other
exceptions cause termination
- by default a procedure can throw all exceptions
- exception problems
- throw clauses are useful but dangerous - must list all possible
exceptions; unlisted exceptions get turned into
unexpected
exceptions
- further exception refinements
- c++ throws several exceptions -
bad_alloc
in new
in
particular
- there's also a non-throwing
new
- this used to be standard
-
auto_pointers
provide a means for automatic resource recovery on
exceptions
- some exception pointers
- don't use them - nasty, asynchronous, implicit control flow
- if you do use them
- make sure they indicate exceptional conditions - don't use them to
exit a loop or return from a procedure; lisp programmers beware
- keep it as simple as possible - short throw-catch relations and
simple values returned
This page last modified on 4 October 2001.