[CSUSB] >> [CompSci] >> /u/faculty/dick/cs320/sebesta/14

CS320 Notes on Exceptions

	http://www.csci.csusb.edu/dick/cs320/sebesta/14.html
 
These notes will give my comments on Sebesta's chapter 14
plus some notes on Exceptions in Java.

14.1 Introduction

Exceptions and Exception handling is a natural way to cope with
Murphy's Law: If anything can go wrong, it will. 

The book mentions some reasons why exceptional circumstances
arise.  It is quite correct... here are some more thoughts

First it is not enough to require people using your code to
do the right thing.  They won't.

You might think that writing subprograms like this:
	subprogram foo(arguments)
	{
		if(arguments are OK) {do it}
		else {do something different}
	}
would be enough.

But in practice you end up having to check every statement
in the "do it" code in turn to see if it is OK to continue.
Each division, each square root, each logarithm, ... and then
every other arithmetic operation to see if it overflows.  Then
check every array and string access to see if the subscript is
within bounds.
	subprogram foo(arguments)
	{
		if(step1 OK)
		{  do step 1;
		   if(step2 OK)
		   { do step 2;
			...
		   } else
			if(alternate step 2 OK)
			{ do alternate step 2;
			...
			}
		   }
		 } else ...
	}
The if-else multiply rapidly.  You end up with code that is not
easy to maintain because the error handling covers  up the "real"
logic of solving the problem.

Exceptions are an idea that handle this problem in a structured way.
They can help preserve the structure of the
problem as well as efficiently checking the validity of the data, and
correctness of each step.

Exceptions help solve another class of difficulties based on the
defining properties of subprograms:
	They return to where it is called.
What happens if the subprogram is called with data that means that
the subprograms problem can not be solved:
	find the real square root of -4.
	find the parent of an orphan.
	find the 13 item in a 12 item array.
The classic "solution" is to terminate or about the whole program.
This is not good when the program is controlling an aircraft or
a pacemaker.  We need an "emergency" exit that gets control back to
the calling program in such a way that the caller knows
	"sorry, wrong number"
	subprogram foo(arguments)
	{
		...
		if(impossible)
			return to caller with error signal;
		...
	}
The nastiest problems in error handling come from reading in user input.
Users do strange things -- like inputting Roman numerals or mistyping
lower and upper case letters.  May favorite example being the clerk who wrote
		NONE
on a form instead of
		0
(The computer accepted the data and converted it to large number).

Notice the C/C++ trick for spotting end of file and other bad
input failures:
	if( cin >> data1 >>data2 >> ....){
		process data
	} else {
		process errors
	}
In C and C++ most commands are also expressions that return a value
that can be tested.  Conventionally in C/C++ 'true' means OK and
'false' means something went wrong.  The Bourne and Korn Shells
in UNIX do something similar.  Prolog also uses a similar technique:
any predicate can do things or else fail...

14.1.1

Key words to remember:
	exception
	exception handling
	exception handler
	raise

Notice that even if all hardware/software exceptions are
handled by the language invisibly... it helps for the programmer
to add new ones.

Notice the primitive ways of avoiding adding a special
construct to a language:
	Returning a status value:  used in C libraries and UNIX Shell
					(also DOS programs!)
	Handing in an argument that is a label in the calling program
		(FORTRAN)
		In Pascal many programmers would define a global label
		at the end of the program for emergencies: 911.
		program whatever
		...
		begin
			...
		911:
		end.
		Procedures and functions could then contain
			goto 911;
		when things went badly wrong.

	Handing a subprogram argument that is called to
	  handle the exception.
		Used in the 'signal' functions in the C library
		for handling interrupts and crashes.
		Variation - X windows call back functions.

14.1.2 Design Issues.

Notice these..

14.1.3 History

Those that do not learn from history are doomed to repeat it.


14.2 PL/I

PL/I is of historical interest.  
So I don't expect you to know the syntax for PL/I.
But PL/I demonstrated the dangers of dynamic exception handling
to such an extent that language designers moved away from using it.
Notice in particular the evaluation subsection 14.2.6.
	Dynamic scoping causes problems.

14.3 Ada

30 years later... statically scoped exceptions.

Key Idea: The idea of a block/compound statement with a set
of error handlers at the end.  Normally, skip the exception
handlers.  If an exception is raised and it is not listed in a
block then try the next block out wards.

Notice the integration of predefined errors with
programmer chosen errors.

14.4 C++

C did not have exceptions.  C++ borrowed them from earlier languages.
I believe the Common LISP gave C++ the words Throw and Catch.
Ada and Clu are the other sources.

Syntax
	try{
		where things go wrong
			includes 'throw expression';
	}
	catch( evidence of problem){
		handle the problem
	}

Notice that an exception can involve throwing a single value of any type
in C++.  This is a debatable choice.

There is no truth in the rumor that at one time C++ had
a
	hurl
command:-)

14.5 Java

Java has an interesting exception feature that raises its head the
moment you try to interact with a user.  This surprises new Java programs:
	http://csci.csusb.edu/public/faculty/dick/Luv.java

Java's exception and error handling has C++-like syntax and
similar semantics.   There is one critical
difference... you can only throw objects that
are in classes derived from the
	Throwable
class.  Throwable objects know how to handle the run time
stack and other useful things.

Error and Exception are ready-made API classes derived from
Throwable.

There are many ready made Exceptions and Errors,
Further it is easy to create more...

Java adds a new piece of syntax to C++.  It
allows you to provide a piece of code to a block that can not be
skipped by an exception in the block.  This simplifies tidying of things.
	(closing files, telnet sessions, releasing storage etc.)

	try {
		block
	}
	catch (arguments)....
	finally ...

I have a list of many of the classes in Java:
	http://www.csci.csusb.edu/dick/samples/java.class.tree.html
This shows a lot of possible, ready made errors and exceptions.
	Object
		Throwable
			Error
			Exception

The Sun compiler enforces a useful piece of logic:
	If you call foo and foo can raise an exception of type E
	then either you will catch E or you will throw it.
(The Law of Karma: The consequences of your actions will catch
up with you.)

Therefore you have to either catch any exceptions that are
documented or document that your code throws them.  Or you get a
compile error!

There is an exception to this rule (of course:-):
	The RunTimeException is too common in beginners code
	and so doesn't have to be explicitly thrown or caught.


Java has extended the function protocol/header to include documentation
of what can be thrown:
	modifiers type name(argument) throws exceptions