Regarding nothrow and @safe

Jonathan M Davis jmdavisProg at gmx.com
Sun Aug 21 13:04:47 PDT 2011


On Sunday, August 21, 2011 12:38:47 Jacob Carlborg wrote:
> On 2011-08-21 02:26, Jonathan M Davis wrote:
> > On Saturday, August 20, 2011 18:18:25 Sean Eskapp wrote:
> >> bearophile:
> >>> As far as I know they have decided to make memory overflow errors,
> >>> so
> >>> they are
> >> 
> >> not exceptions, you can't catch them. Other people will confirm this
> >> or not.
> >> 
> >> In this case, how would you go about handling out-of-memory
> >> situations? A systems programming language should certainly give the
> >> programmer the option to deal with this.
> > 
> > The short answer: You don't. It's an incredibly bad idea.
> > 
> > The long answer: You catch Error - or OutOfMemoryError if you want that
> > specific one. So, you could try and catch it and handle it, but most of
> > the cleanup during the unwinding of the stack gets skipped. scope
> > statements and destructors don't get called. Your program is not likely
> > to be in state where it makes any real sense to try and continue. You
> > _can_ do it, but it's a bad idea.
> > 
> > - Jonathan M Davis
> 
> What about if you have an application doing heavy image/video
> processing, the application could empty some caches or similar. The
> application could still work, just not as fast as with caches.

Things do _not_ get cleaned up properly when an Error is thrown. Destructors, 
finally blocks, and scope statements are skipped when any type of exception 
which is not derived from Exception (directly or indirectly) is thrown. Errors 
are considered unrecoverable.

Now, you _can_ catch Errors. You _can_ try and continue to execute your 
program. But, there are no guarantees that your program is still in a sane 
state, because anything which could have been affected by destructors, finally 
blocks, and scope statements being skipped could be in a state which your 
program does not expect and cannot handle.

Read page 307 of TDPL. It talks about "nothrow Functionsa and the Special 
Nature of Throwable." What it says applies to all throwables which are not 
derived from Exception. That's why when you have a nothrow function, like this

void func() nothrow
{
    try
        throwFunc();
    catch(Exception e)
        assert(0, "It threw!");
}

void throwFunc()
{
    throw new Exeception("Exception!");
}

catching Exception is enough. Anything not derived from Exception is not 
considered in nothrow and is considered unrecoverable. So, attempt to recover 
from an OutOfMemoryError at your own peril.

In the case of your image/video application, it might be able to recover and 
continue if you were able to catch the OutOfMemoryError at its source before 
it started propagating up the calcl stack, but as soon as it starts skipping 
stuff that a normal Exception wouldn't have skipped, your program is effectively 
in an invalid state. If you really wanted to do what you describe, you'd 
probably want to use custom memory allocators, which is on the todo list, I 
believe (and is one of the major reasons why Andrei isn't farther on 
std.container yet; he wants to sort out his custom memory allocator scheme 
first). But trying to catch and recover from an Error is generally a _very_ bad 
idea.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list