assert(...) is a macro in C. That's a BadThing
Assertions are about testing a boolean condition, and flaming out if the condition is false. It's essentially a way of embedding a unit test in your product, which runs every time.
People can write "assert(x=5);" which has the unintended effect of only setting the value of x when debugging is turned on.
Option one: ShipWithAssertionsOn
Option two: Declare that calculating an assertion should not access a volatile variable or write to memory outside the stack frame of the assertion. Call these functions side-effect free (SEF).
Option three: DontDoThat.
Only problem is that you suddenly have to know, for everything, whether it writes outside its stack frame. This is an insoluble problem in the general case.
A reasonable solution is to limit the set of assertions to what is obviously SEF. Many functions are obviously SEF. Many of those which are SEF, but not obviously SEF, can be re-written to be more obvious.
This doesn't cover the "assertion smashes stack" problem, but that's rare in practice.
It's a big pain to make the toolchain keep track of what is proven side-effect free. Still, it's probably useful for people who must program at the level where assertions are really useful in the first place. Beyond that, there are UnitTest
s. This is, indeed, probably the correct boundary for those who insist on using assertions at all.
Several compilers (including GNU C -- http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html
) use the pure
keyword to indicate that a function is side-effect-free.
They throw a warning/error if a function with the pure
tag directly calls any function that does not have the pure
tag. (Indirect calls are caught when that other function is compiled).
It's a big pain to make the toolchain keep track of what is proven side-effect free.
I don't see why. It doesn't seem any more difficult than, say, making sure all the arguments in a function call have the the right types as defined in the function prototype.
- Even that doesn't guarantee the ability to keep track of purity. Here is a better solution, which requires no new keyword: --Samuel A. Falvo II
- If a routine modifies any member of any argument passed to it (including all implicit arguments, such as this), the routine is impure.
- If a routine even potentially calls at least one method, procedure, or function that is itself known to be impure, then the routine is impure.
- If a routine invokes an externally defined routine, written in a language other than the current language (e.g., an external assembly language routine), then the routine is impure (since the compiler doesn't know or cannot prove the purity of the external routine, it must err on impurity just in case). If you are willing to introduce a new keyword, you can use "pure" to annotate external routines appropriately, so as to convince the compiler's trust.
Of course, adding the pure
tag to a function can be a hassle. You have to track down all the functions it calls and add the pure
tag to them, then all the functions *they* call. Reminds me of the const
ripple effect (ConstIsaVirus