DIP33: A standard exception hierarchy

Lars T. Kyllingstad public at kyllingen.net
Mon Apr 1 05:12:55 PDT 2013


On Monday, 1 April 2013 at 11:52:47 UTC, monarch_dodra wrote:
> On Monday, 1 April 2013 at 11:33:57 UTC, Lars T. Kyllingstad 
> wrote:
>> On Monday, 1 April 2013 at 11:23:50 UTC, monarch_dodra wrote:
>>> On Monday, 1 April 2013 at 11:08:16 UTC, Lars T. Kyllingstad 
>>> wrote:
>>>> It's time to clean up this mess.
>>>>
>>>> http://wiki.dlang.org/DIP33
>>>
>>> A quick comment about your "Error" section. You say:
>>>
>>> "In general, Errors should not be caught, primarily because 
>>> they indicate that the program logic is compromised, and that 
>>> the program may therefore be in an invalid state from which 
>>> there is no recovery".
>>>
>>> It is actually much worst than that: errors bypass the entire 
>>> exception handling mechanism, blasting through code that 
>>> would handle destructors, and even flying through functions 
>>> that are nothrow. They don't just indicate a "potential" 
>>> invalid state, they actually *put* the program in an invalid 
>>> state, from which there is no recovery.
>>>
>>> That is the main mechanical difference between an "error" and 
>>> an "exception", it is not just a philosophical "logic vs 
>>> runtime".
>>
>> I had forgotten about that.  Personally, I think that is crazy.
>> Errors ought to propagate just like Exceptions, they just 
>> shouldn't be a part of your "normal" error-handling mechanism.
>
> I don't know, I find the approach kind of genius personally. If 
> it is a logic error, and your program is going to die, then why 
> pay for cleanup? You are getting the radical efficiency of a 
> normal assert, but with the opportunity to die like with an 
> exception.

But if all cleanup code is bypassed, what is the point in using 
the exception mechanism in the first place?  Why not just abort() 
and be done with it?

I can think of two reasons for throwing an Error rather than 
aborting directly:
1. You want a kind of "graceful" shutdown, in which destructors 
*are* called and make their best attempt at cleaning things up.
2. You want to catch it at some point, and perform some manual 
cleanup.

But if (1) does not happen, can you even hope to do something 
useful with (2)?  Your program is in the worst possible state it 
can be!

> The nicest part (IMO), is that thanks to this, you can assert 
> in a nothrow function, without violating its nothrow-ness 
> (which we do all over phobos, and even with built-in arrays).

Well, there are two benefits to nothrow:
1. It makes a guarantee to the programmer that a function does 
not throw, and the programmer consequently does not need to worry 
about exception handling.
2. The compiler can elide exception handling code altogether, 
which improves performance.

Personally I think (1) is the most important, and we could 
maintain this guarantee even if Error and OutOfMemory propagated 
just like Exception.  We'd just redefine 'nothrow' to mean "does 
not throw Exception".

Then, we could introduce a new attribute, e.g. __hard_nothrow, to 
allow for (2).  This would require the programmer to handle Error 
and OutOfMemory too, and importantly, we could apply it to most C 
functions.


>>> Under this situation, I'm wondering how the "OutOfMemory" is 
>>> dealt with (you don't explain). The only logical explanation 
>>> I can see is:
>>> - It is not an exception and is not caught by 
>>> "catch(Exception)".
>>> - But it is not an error either, so does not corrupt the 
>>> program state.
>>> => Goal: It is hard to catch, but you *can* recover from it.
>>> Is this correct? Is this what we are going for?
>>
>> That was the idea, yes.
>
> I like the idea, but it would be particularly breaking change 
> for nothrow functions though:
>
> void foo() nothrow
> {
>     try
>     {
>         throw new OutOfMemory()
>     }
>     catch (Exception /+e+/)
>         {}
> }
>
> "Error: foo is nothrow yet may throw"
>
> ...what ...? But I caught the Exception!
>
> The bypass would be giving OutOfMemory the same semantics as an 
> Error, but then, it would just be an actual Error...

I think OutOfMemory should not be restricted by nothrow, and I 
propose to solve it as described above.

Lars


More information about the Digitalmars-d mailing list