Exception/Error division in D

Steven Schveighoffer schveiguy at yahoo.com
Thu May 24 11:39:34 PDT 2012


On Thu, 24 May 2012 06:27:12 -0400, Denis Shelomovskij  
<verylonglogin.reg at gmail.com> wrote:

> Let's talk about an abstract situation without caring about breaking  
> existing code, current docs, implementation etc.
>
> Definitions:
> * an Exception is something that tigers scope guards and executes  
> catch/finally blocks if thrown;
> * an Error is something that doesn't do it.

I'll give you a different definition:

* an Exception is something that can be handled far away from the context  
of the error, because the system can safely unwind the stack.
* an Error must be handled at the point the error occurred, or the program  
state is by definition invalid.

>
> As a result _we can't do any clean-up if an Error is thrown_ because  
> scope guards and catch/finally blocks aren't executed and the program is  
> in invalid state because of this. Of course it's theoretically possible  
> to code without scope guards and catch/finally blocks but isn't  
> applicably for a real project. E.g. in some editor if and Error is  
> thrown there is no ability to save opened documents.
>
>
> Main Question: What do you think can be an Error?
>
> Can "Integer Divide by Zero" be an Error? Definitely, not.

I agree with you there.  However, the problem isn't nearly as bad as you  
say.  The runtime doesn't actually deal with SIGFPE on Unix based systems,  
and most places where an "Error" is thrown, it's within asserts, which are  
compiled out in release code.

If you get one of these, you can handle the signal.  I think on Windows  
it's handled for you, but there should be a way to intercept this and do  
recovery.

> Can "Access Violation" be an Error? No, because it's very common to  
> access a field/virtual member function of a null object.

I'd argue this is unrecoverable.  Access Violation results from  
corruption, and the damage has already been done.  Even a null pointer  
access can be the cause of previous corruption.  There is no "recovery"  
 from memory corruption.  There is no way to plan for it.

Now, if you want to handle it specifically for your program, that should  
be doable, at your own risk.  But there's no way throwing an Exception is  
a valid result.

> Can "Out of memory" be an Error? No, because e.g. if I read a user file  
> that require me to create a large array (> 100 MiB, e.g.) I don't want  
> to crash, but just tell, that "Dear user, the file can't be opened  
> because it requires..."

Right, out of memory is only an error if your program's invariant depends  
on the memory allocation.  You can plan for the above easily enough, but  
not realistically for all tasks and all library code that require  
allocation.

For example, let's say you are restructuring a hash table, and you  
reallocate some nodes.  You have half transferred over the old structure  
to the new structure, and you run out of memory.  How to recover from this?

In summary, I think we can adjust Windows divide by zero errors to allow  
you to handle them manually, the Posix version is fine (no Error is  
generated), access violations are unequivocally Errors, and out of memory  
should be fixable by making allocation routines that do not throw (just  
return null).

An interesting idea would be to allow a global "handler" for all errors.   
So if you throw an Exception, it unwinds the stack like normal.  If you  
throw an Error, it checks a handler to see if you want to handle that  
error (via registering a function/delegate), and if not handled throws  
Error without properly unwinding the stack.

-Steve


More information about the Digitalmars-d mailing list