[comp.lang.modula3] checked run-time errors and exceptions

moss%ibis@cs.umass.edu (Eliot Moss) (02/11/91)

>>>>> On 8 Feb 91 17:42:23 GMT, doug@snitor said:

doug> The preface to the Modula-3 report says:
doug>   "The goal of Modula-3 is to be as simple and safe as it can be
doug>    while meeting the needs of modern systems programmers."
doug> Modula-3 can't meet these goals until NEW has been redefined
doug> to raise an exception on memory exhaustion.

I tend to agree with this, and NEW is not the only problem. I think the
language committee should revisit the issue of checked run-time errors versus
exceptions with an eye to supporting the construction of very robust programs:
ones that attempt to handle errors on their own and continue operation.
Running out of storage in NEW is an obvious case, but there are undoubtedly
others. I would tend to argue that even though accessing beyond the bounds of
an array is an error (i.e., should never happen in a properly coded program),
it may still be reasonable for a robust program to attempt to recover from
bugs in some of its routines.

Along these lines, CLU defined a number of specific exceptions for various
situations, including "bounds", "end_of_file", and the like, and had a
(slightly special) exception called "failure" for indicating that the
underlying support abstraction(s) had failed. Running out of storage was one
failure situation; accessing an uninitialized variable was (supposed to be)
another (not fully implemented to my knowledge, but more modern compiler
technology makes it easier); de-referencing a NIL pointer is a good example in
Modula-3.

A robust program could be built that would ty to clean up as much as possible
from a failure exception and abort or skip the particular task it was working
on at the time, perhaps logging the failure for maintainers (though log
overflow should also be considered!). Such a program needs to be a bit
intelligent about whether an error is recoverable (and the action should be
restarted) or not (in which case the action should *not* be restarted, to
avoid an infinite loop; at the very least, the actio should be deferred if at
all possible). This means that the exceptions need to be standardized enough
for programs to be able to tell the difference.

All of this needs to be standardized as much as possible, for portability,
though there are bound to be OS-, compiler-, and application-specific things
that cannot be dealt with in the language definition.

		J. Eliot B. Moss, Assistant Professor
		Department of Computer and Information Science
		Lederle Graduate Research Center
		University of Massachusetts
		Amherst, MA  01003
		(413) 545-4206, 545-1249 (fax); Moss@cs.umass.edu

harbison@bert.pinecreek.com (Sam Harbison) (02/12/91)

I also think all checked run-time errors should be mapped to exceptions, for
reasons already presented. I think there's value in NOT changing the language
any more, but this issue is close to my "must fix" threshold. If the 
language committee prefers not to make the change, I would be in favor
of proposing a model of errors-as-exceptions that "politically correct"
implementations of Modula-3 would be encouraged to follow, as permitted but
not required by the language spec.

Sam Harbison
Pine Creek Software, Pittsburgh, PA.
+1 412 681 9811

mjordan@src.dec.com (Mick Jordan) (02/12/91)

In article <9102111557.AA02459@ibis.cs.umass.edu>, moss%ibis@cs.umass.edu (Eliot Moss) writes:

> I tend to agree with this, and NEW is not the only problem. I think the
> language committee should revisit the issue of checked run-time errors versus
> exceptions with an eye to supporting the construction of very robust programs:
> ones that attempt to handle errors on their own and continue operation.
> Running out of storage in NEW is an obvious case, but there are undoubtedly
> others. I would tend to argue that even though accessing beyond the bounds of
> an array is an error (i.e., should never happen in a properly coded program),
> it may still be reasonable for a robust program to attempt to recover from
> bugs in some of its routines.
> 

If my memory is correct, two committee members including myself, argued strongly
for checked run-time errors to be mapped in the "fail" exception, which would
be implicitly included in every RAISES clauses. This is the situation in
Modula-2+, which even names this exception as FAIL. On can catch FAIL with
an ELSE handler which, when used with restraint, provides adequate
last ditch bullet-proofing. The argument against boils down to implementation
difficulties in mapping some hardware failures (efficiently) into exceptions.
(Having said that, the Olivetti implementation did map failures into an 
exception, which could be caught by ELSE. We used this to good effect in
one program which, when it crashed, would bring down the entire OS).

However, I have a strong dislike for naming individual failure exceptions and,
therefore, encouraging, for example, code which catches NIL faults. There is 
something very bizarre about explicitly catching what are truly programming
errors. Although running out of memory is not a programming error, it is
effectively a failure of the Modula-3 abstract machine, and I am curious to
know how you can write portable code to recover from it, given that you must
be very careful not to call any code which might call NEW again.

Mick Jordan

new@ee.udel.edu (Darren New) (02/13/91)

In article <1991Feb11.152850.1851@src.dec.com> mjordan@src.dec.com (Mick Jordan) writes:
>Although running out of memory is not a programming error, it is
>effectively a failure of the Modula-3 abstract machine, and I am curious to
>know how you can write portable code to recover from it, given that you must
>be very careful not to call any code which might call NEW again.

When I've needed to do such a thing, I've allocated space at the start
of execution, and when malloc() returned NULL, I freed that space and
cleaned up. Hence, the cleanup code could reuse that space to recover.
Of course, how much space to initially allocate is problematic, but
since I was using C it wasn't too hard to handle.  Surely this is already
handled in Smalltalk, C, Ada, etc.  Why would Modula-3 be so different?
-- 
--- Darren New --- Grad Student --- CIS --- Univ. of Delaware ---
----- Network Protocols, Graphics, Programming Languages, 
      Formal Description Techniques (esp. Estelle), Coffee, Amigas -----
              =+=+=+ Let GROPE be an N-tuple where ... +=+=+=

ogden@seal.cis.ohio-state.edu (William F Ogden) (02/13/91)

Mick Jordan writes:

>   ... Although running out of memory is not a programming error, it is
>effectively a failure of the Modula-3 abstract machine, and I am curious to
>know how you can write portable code to recover from it  ...

A satisfactory abstract machine can't present the illusion of an infinite
memory space when it can't sustain it. All computers are resource bounded,
and accidentally running out of memory should be considered a programming
error at some level. Invoking the NEW operator with inadequate remaining
memory is violating its precondition just as surely as invoking the divide
operator with a zero second argument is.

The only difference is that while a prudent programmer can always prevent
the problem with divide (by checking for a zero if he is unsure of his second  
argument), there is no general way to know when he is about to misuse NEW.
Adding an exception mechanism doesn't solve the problem, because in many
situations it is already too late to recover gracefully (or at all). 
Some additional condition of memory checking operation is needed if
the language is going to provide adequate support for sound programming.
/Bill

schoebel@bs3.informatik.uni-stuttgart.de (Thomas Schoebel) (02/13/91)

In article <1991Feb11.152850.1851@src.dec.com> mjordan@src.dec.com (Mick Jordan) writes:

>something very bizarre about explicitly catching what are truly programming
>errors. Although running out of memory is not a programming error, it is
>effectively a failure of the Modula-3 abstract machine, and I am curious to
>know how you can write portable code to recover from it, given that you must
>be very careful not to call any code which might call NEW again.
>
>Mick Jordan

I don't agree with this failure of the abstract machine. There are cases
when a programmer wants to use all *available* memory, e.g. when
implementing a cache. Such a program will run with less cache memory also.
The really amount of memory is runtime dependant, but *not* the
semantics of the program.

From a general purpose language I will expect to support me with
information about available ressorces, allowing to make runtime
decicions about ressource managing strategies.

Thomas Schoebel

E-mail: schoebel@ifi.informatik.uni-stuttgart.de
Phone:  +49 711 121-1409