digitalmars.D - [Warning] Side effects in asserts
- Stewart Gordon (27/27) Jul 23 2004 There seems to be an idiom I've got a bit carried away with
- Kris (7/34) Jul 23 2004 I've noticed that the compiler will leave anything that might have a
- Stewart Gordon (10/15) Jul 26 2004 Maybe, but it's certainly not required to. Indeed, if it really wants
- Kris (12/27) Jul 26 2004 Now I'm trying to recall the context ... uhhh (clickety clickety whirrr ...
-
Stewart Gordon
(21/30)
Jul 26 2004
- Sean Kelly (9/11) Jul 23 2004 Yup. Same problem in C/C++. I ended up making a new macro for this sit...
There seems to be an idiom I've got a bit carried away with
assert(DoSomething());
where DoSomething is some system call that returns non-zero to indicate
that it's succeeded. I recall it being used in winsamp.d, and possibly
also some of the other examples. It's a convenient way of doing a
system call and making sure it's succeeded in one line.
Except that it isn't:
"Asserts evaluate the expression. If the result is false, an AssertError
is thrown. If the result is true, then no exception is thrown. It is an
error if the expression contains any side effects that the program
depends on. The compiler may optionally not evaluate assert expressions
at all. The result type of an assert expression is void. Asserts are a
fundamental part of the Design by Contract support in D."
In other words, not only will it not check for failure in the release
version, but it also probably won't evaluate the body of the assert at
all, and so the system call necessary to the program won't happen.
So I thought I'd better warn you all before you get even more carried
away with this bad idiom. If you want to check if a system call has
failed, use a real if statement or ?= expression. This will also make
it possible to throw an exception of choice rather than an AssertError,
as you'll probably want to do anyway.
Let's see if I can get these cleaned up in time for SDWF 0.3....
Stewart.
--
My e-mail is valid but not my primary mailbox, aside from its being the
unfortunate victim of intensive mail-bombing at the moment. Please keep
replies on the 'group where everyone may benefit.
Jul 23 2004
I've noticed that the compiler will leave anything that might have a
side-effect in place. That is, when asserts are disabled your DoSomething()
will still be in the code-line. This is both a blessing and a curse, but it
does identify another good reason for the existence of version()
- Kris
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:cdrc9e$24u0$1 digitaldaemon.com...
There seems to be an idiom I've got a bit carried away with
assert(DoSomething());
where DoSomething is some system call that returns non-zero to indicate
that it's succeeded. I recall it being used in winsamp.d, and possibly
also some of the other examples. It's a convenient way of doing a
system call and making sure it's succeeded in one line.
Except that it isn't:
"Asserts evaluate the expression. If the result is false, an AssertError
is thrown. If the result is true, then no exception is thrown. It is an
error if the expression contains any side effects that the program
depends on. The compiler may optionally not evaluate assert expressions
at all. The result type of an assert expression is void. Asserts are a
fundamental part of the Design by Contract support in D."
In other words, not only will it not check for failure in the release
version, but it also probably won't evaluate the body of the assert at
all, and so the system call necessary to the program won't happen.
So I thought I'd better warn you all before you get even more carried
away with this bad idiom. If you want to check if a system call has
failed, use a real if statement or ?= expression. This will also make
it possible to throw an exception of choice rather than an AssertError,
as you'll probably want to do anyway.
Let's see if I can get these cleaned up in time for SDWF 0.3....
Stewart.
--
My e-mail is valid but not my primary mailbox, aside from its being the
unfortunate victim of intensive mail-bombing at the moment. Please keep
replies on the 'group where everyone may benefit.
Jul 23 2004
Kris wrote:I've noticed that the compiler will leave anything that might have a side-effect in place.Maybe, but it's certainly not required to. Indeed, if it really wants to generate efficient release code then it would probably leave it out.That is, when asserts are disabled your DoSomething() will still be in the code-line. This is both a blessing and a curse, but it does identify another good reason for the existence of version()<snip> I'm not sure what you mean. How would versions get around this? Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jul 26 2004
Now I'm trying to recall the context ... uhhh (clickety clickety whirrr ...)
Ah, right. I meant that since assert() will potentially leave
side-effect-causers in the code (such as a function call), a construct such
as version(){} is needed in the language, so one can be explicit about
whether you really do have side effects or not. That is, wrapping the
assert() inside a version(), or a debug() at least allows you to be explicit
about removing the assert() and all other checks. The assert() by itself is
not sufficiently explicit.
- Kris
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:ce2j5j$mfu$1 digitaldaemon.com...
Kris wrote:
I've noticed that the compiler will leave anything that might have a
side-effect in place.
Maybe, but it's certainly not required to. Indeed, if it really wants
to generate efficient release code then it would probably leave it out.
That is, when asserts are disabled your DoSomething()
will still be in the code-line. This is both a blessing and a curse, but
it
does identify another good reason for the existence of version()
<snip>
I'm not sure what you mean. How would versions get around this?
Stewart.
--
My e-mail is valid but not my primary mailbox, aside from its being the
unfortunate victim of intensive mail-bombing at the moment. Please keep
replies on the 'group where everyone may benefit.
Jul 26 2004
Kris wrote:
Now I'm trying to recall the context ... uhhh (clickety clickety whirrr ...)
Ah, right. I meant that since assert() will potentially leave
side-effect-causers in the code (such as a function call), a construct such
as version(){} is needed in the language, so one can be explicit about
whether you really do have side effects or not. That is, wrapping the
assert() inside a version(), or a debug() at least allows you to be explicit
about removing the assert() and all other checks. The assert() by itself is
not sufficiently explicit.
<snip>
Release and debug aren't the only compilation modes. There's the
default mode - DBC, asserts and ABC enabled, but debug blocks not.
And at the moment, we don't (according to the docs) have a version
identifier for release. And anyway, it would keep the code concise to
just do something like
// system call with no side effect
assert (CheckSomething());
// system call with side effect
if (!DoSomething()) assert(false);
// or
if (!DoSomething()) throw new SomeException;
A version block around the first assert would be pointless, as it would
be similar to "language features for the purpose of compensating for
primitive compiler technology".
Stewart.
--
My e-mail is valid but not my primary mailbox, aside from its being the
unfortunate victim of intensive mail-bombing at the moment. Please keep
replies on the 'group where everyone may benefit.
Jul 26 2004
In article <cdrc9e$24u0$1 digitaldaemon.com>, Stewart Gordon says...
There seems to be an idiom I've got a bit carried away with
assert(DoSomething());
Yup. Same problem in C/C++. I ended up making a new macro for this situation:
#ifdef NDEBUG
inline void predicate( bool ) {}
#else
inline void predicate( bool exp ) { assert( exp ); }
#endif
You could do something similar in D.
Sean
Jul 23 2004









Stewart Gordon <smjg_1998 yahoo.com> 