A nice blog post about assertions, preconditions, invariants and their usage:

http://blog.regehr.org/archives/1091

It shows how D avoids some troubles, and offers most of what's needed.

The checkRep() Idiom

It could go in the D invariant. I use it often.


The second way to accidentally change the state of the
program is like this:

assert (treeDepth() == 7);

but unfortunately treeDepth() changes the value in some
variable or heap cell, perhaps via a longish call chain.

In case it isn't totally clear, the problem with side-effects
in assertions is that we'll test our program for a while, decide it's good, and do a release build with assertions turned off and of course suddenly it doesn't work. Or, it might be the release version that works but our debug build is broken by a side-effecting assertion. Dealing with these problems is highly demoralizing since assertions are supposed to save time, not eat it up. I feel certain that there are static analyzers that warn about this kind of thing. In fact, the original paper about the work that became Coverity's tool mentions exactly this analysis in Section 4.1, and also gives plenty of examples of this bug. This is an area where language support for controlling side effects would be useful. Such support is extremely primitive in C/C++.

On this topic I have recently added an Enhancement Request, to disallow side effects in assert():

https://d.puremagic.com/issues/show_bug.cgi?id=12028

Two simple examples of code that is meant to be forbidden:

int foo(ref int y) pure nothrow {
    return y++;
}
void main() {
    int x;
    assert(++x);
    assert(foo(x));
}

Bye,
bearophile

Reply via email to