On Thursday, 31 July 2014 at 17:10:27 UTC, H. S. Teoh via
Digitalmars-d wrote:
On Thu, Jul 31, 2014 at 02:05:29AM +0000, Tofu Ninja via
Digitalmars-d wrote:
On Wednesday, 30 July 2014 at 22:01:23 UTC, Walter Bright
wrote:
>3. Use of assert to validate input is utterly wrong and will
>not be
>supported. Use such constructs at your own risk.
When exactly is it 'ok' to use assert then?
If asserts are not allowed to be used to verify inputs....
then by
extension, they can not be used to verify any derivative of an
input.
No that doesn't make sense. The idea behind input sanitization
is that
user-facing APIs receive arbitrary, unverified input from
outside, and
before you use that data, you scrub it. After scrubbing it, it's
perfectly OK to use assert to verify its validity -- because if
it's
still invalid, there's a bug in your scrubbing algorithm. The
scrubbed
input *is* a derivative of the input, but you can't say that
you can't
use assert on it!
(And if you *don't* scrub your data before using it, your
design is
flawed and should be fixed.)
So by that definition, asserts are only ok to use on any thing
known
at compile time... that makes them utterly useless....
Your definition is wrong. ;-) The idea behind asserts is that
you're
verifying *program logic*, not checking arbitrary input data.
If you
have an algorithm that computes a square root, for example,
you'd use an
assert to verify that the square of the result equals the input
--
because if not, that means something has gone wrong with your
square
root algorithm. But you shouldn't use an assert to verify that
the input
to the square root algorithm is a valid numerical string --
because the
user could have typed "abc" instead of a number. Rather, you
should
scrub the user input and throw an exception when the input is
invalid.
After scrubbing, however, it's perfectly valid to assert that
the input
must be a valid number -- because if not, it means the *logic*
in your
scrubbing algorithm is flawed (perhaps it missed a corner case).
It's true, however, that this simple idea is not always so
simple in
practice. One has to draw a line between "user input" and
"internal
state" somewhere, and it's not always obvious where that line
falls. For
example, viewed as a whole, the entire software application may
be
considered a system that takes input from outside, so "user
input" means
things like keystrokes, mouse movements, etc.. But internally,
the
system may consist of multiple components, and when data is
passed
between components, should they be treated as "internal state"
or "user
input"? Should library APIs treat application input as
"external input"
and vet it before use, or is it OK to use assert to enforce(!)
the
validity of data passed internally between the application's
components?
It's not always easy to decide, and sometimes judgment calls
have to be
made.
T
With that logic(and the proposed optimizations that this whole
thing is about), weird stuff like this happens...
void foo(int x)
{
if(x != 0) throw ...;
assert(x == 0);
}
The if check could be removed because assert will be assumed to
always be true in release... so x could never not equal 0.... the
assert just nuked my scrubbing logic...