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...

Reply via email to