DMD 1.027 and 2.011 releases

eao197 eao197 at intervale.ru
Thu Feb 28 01:24:29 PST 2008


On Thu, 28 Feb 2008 07:27:24 +0300, Russell Lewis  
<webmaster at villagersonline.com> wrote:

> I wonder if asserts() should be the exception to nothrow.  Like eao197,  
> I normally run my programs with assert()s turned on.  But it would be a  
> shame to lose nothrow because of that.
>
> Are assert()s catchable?

Yes, it is catchable:

import std.stdio;
import std.asserterror;

void do_something( int i, int j )
   in
     {
       assert( i < j, "i must be lesser than j" );
     }
   body
     {
       writefln( "i=", i, ", j=", j );
     }

void main()
   {
     try
       {
         do_something( 0, 1 );
         do_something( 1, 0 );
       }
     catch( AssertError x )
       {
         writefln( x );
       }
   }

> Other than in some sort of weird systems programming context (where you  
> are running one program inside another), why would you want to catch  
> them?

It is not necessary to catch AssertError. Sometimes it is necessary to  
catch any error. For example, in a HTTP-server you could start processing  
of a new request and catch different kinds of errors to make appropriate  
response:

void processNewRequest( SomeRequestData request )
   {
     try
       {
         requestProcessingActions( request );
       }
     catch( Error x )
       {
         logError( x );
         classifyErrorAndMakeAppropriateResponse( x );
       }
   }

There is no difference between some application-logic error, index out of  
range error, no memory error or AssertError. The request processing failed  
and the reason must be logged.

>  (I'm sure somebody has a compelling example...but would that example be  
> ruined by asserts-that-penetrate-nothrow.)

May be I don't understand your question, but I think that nothrow should  
help write exception-safe code. For example, some resource cleanup actions  
in finally statements:

auto firstStream = createStream();
auto secondStream = createStream();
auto thirdStream = createStream();

try {
   firstStream.open( 'first' );
   secondStream.open( 'second' );
   thirdStream.open( 'third' );
   ... some actions with firstStream, secondStream and thirdStream ...
}
finally {
   // All stream should be closed here.
   firstStream.close;
   secondStream.close;
   thirdStream.close;
   ... some other cleanup code...
}

It is rather naive resource cleanup code, because without nothrow  
specification we can't assume that a 'close' call doesn't throw an  
exception. If close can throw exceptions we must rewrite it, for example:

finally {
   void safeClose( Stream s ) { try { s.close; } catch( Error ) {} }
   safeClose( firstStream );
   safeClose( secondStream );
   safeClose( thirdStream );
   ... some other cleanup code...
}

But if we know that close doesn't throw exceptions then we can write less  
code (without safeClose helper function). And I suppose that 'nothrow' is  
a promise of function's developer that the function doesn't throw an  
exception.

But if 'close' is written as:

close() nothrow
   in { assert( is_opened(), "close() must be called only in stream is  
open" ); }
   body { ... }

I think that such implementation brokes a promise about non-throwing  
exception. For example, what if some exception is thrown at  
secondStream.open("second") in the sample above? We are going to finally  
statement, successfully close firstStream, but get AssertError at  
secondStream.close(). It breaks finally statement and we have no chance to  
perform other cleanup code.

So I think that nothrow is a contract which is violated by any assert in  
in/out statements. And because of that nothrow shouldn't be used with  
in/out contracts.

But here is another kind of problem with nothrow. I don't know is it  
possible to write really exception free code in D (AFAIK it is impossible  
on JVM/.NET because VM could raise some of it internal exception at any  
moment). Exceptions could be everywere -- on accessing array items, on  
string concatenations, on new statements, on calling some functions with  
pre/postconditions and so on. So probably nothrow function could throw  
some kind of exceptions even if function's writter don't known about them  
(it reminds me unchecked exceptions in Java which could be thrown despite  
of method's exception specification). In such case AssertError could be  
one of such 'unchecked exception' in D, and in such case nothrow could be  
combined with in/out statements. But in such case the profit from nothrow  
is under doubt for me.

Disclaimer: I know that my sample with streams and resource cleanup in  
finally statement could be rewritten in different ways. It is just a  
sample.

>
> eao197 wrote:
>> On Wed, 27 Feb 2008 16:56:34 +0300, Christopher Wright  
>> <dhasenan at gmail.com> wrote:
>>
>>> eao197 wrote:
>>>> B.foo may looks like:
>>>>  void foo() nothrow
>>>>   in { assert( <some condition> ); }
>>>>   out { assert( <some condition> ); }
>>>>   body { <some code without exception> }
>>>>  Body of B.foo() doesn't throw exception but assert in  
>>>> pre/postcondition could do that. A call of B.foo could produce  
>>>> exception but B.foo is declared as 'nothrow' :(
>>>>
>>>
>>> I'm happy with that. Contracts aren't compiled in release mode, and  
>>> they aren't part of the function; they're part of the tests. I'd hate  
>>> to have to avoid one language feature for reliability in order to gain  
>>> another one.
>>  People are different. You want to compile your programs in release  
>> mode to remove any run-time checks and contracts. I want to save them  
>> in my programs to catch errors at the most earliest stage ('fail fast'  
>> principle is very important in server-side systems). But a programing  
>> language must provide logical and consistent rules for each of us.
>>  --Regards,
>> Yauheni Akhotnikau



-- 
Regards,
Yauheni Akhotnikau


More information about the Digitalmars-d-announce mailing list