On 09/11/2014 21:33, Walter Bright wrote:
On 11/7/2014 7:00 AM, Bruno Medeiros wrote:
Let me give an example:
double sqrt(double num) {
assert(num >= 0);
...
With just this, then purely from a compiler/language viewpoint, if the
assert is
triggered the *language* doesn't know if the whole program is corrupted
(formatting the hard disk, etc.), or if the fault is localized there,
and an
error/exception can be thrown cleanly (clean in the sense that other
parts of
the program are not corrupted).
So the language doesn't know, but the *programmer* can make a
reasoning in each
particular assert of which domains/components of the program are
affected by
that assertion failure. In the sqrt() case above, the programmer can
easily
state that the math library that sqrt is part of is not corrupted, and
its state
is not totally unknown (as in, it's not deadlocked, nor is it
formatting the
hard disk!).
Making such an assumption presumes that the programmer knows the SOURCE
of the bug. He does not. The source could be a buffer overflow, a wild
pointer, any sort of corruption.
Very well then. But then we'll get to the point where enforce() will
become much
more popular than assert to check for contract conditions. assert()
will be
relegated to niche and rare situations where the program cant really
know how to
continue/recover cleanly (memory corruption for example).
That idiom is fine with me actually - but then the documentation for
assert
should reflect that.
I created this thread because it is an extremely important topic. It has
come up again and again for my entire career.
There is no such thing as knowing in advance what caused a bug, and that
the bug is "safe" to continue from. If you know in advance what caused
it, then it becomes expected program behavior, and is not a bug.
assert() is for bug detection, detecting state that should have never
happened. By definition you cannot know it is "safe", you cannot know
what caused it.
enforce() is for dealing with known, expected conditions.
As I mentioned before, it's not about knowing exactly what caused it,
nor knowing for sure if it is "safe" (this is an imprecise term anyways,
in this context).
It's about making an educated guess about what will provide a better
user experience when an assertion is triggered: halting the program, or
ignoring the bug and continuing the program (even if admittedly the
program will be in a buggy state).
I've already mentioned several examples of situations where I think the
later is preferable.
Just to add another one, one that I recently came across while coding,
was an assertion check that I put, which, if it where to fail, would
only cause a redundant use of memory (but no NPEs or access violations
or invalid state, etc.).
--
Bruno Medeiros
https://twitter.com/brunodomedeiros