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