Assert() in the hands of bad coders
blog.erratasec.com
blog.erratasec.com
Normally, asserts are only compiled into debug versions
of the code, and removed for release versions.
I know a lot of languages default to this, and it always seemed like a bad decision to me. The performance benefits of most checks are trivial compared to the major downside of not testing the exact code you release.Several times I've had to track down bugs that have been very difficult to find, as they were 'fixed' by side effects of assert statements and hence didn't show up in debug builds.
If a check really can't be performed in the release version for performance reasons, just separate it out into a unit test.
In those cases, the assert() was used incorrectly. However, that's not a reason to include the assert code in release builds.
In a similar way, source code will often have troubleshooting code such as:
#if _DEBUG // or #ifndef NDEBUG
std::cerr << "inspect size: " << invoices.size() << std::endl;
// more debugging-related code ...
#endif
Just because some programmers mistakenly put unintended side-effects in between the #if_DEBUG/#endif doesn't mean we want that code in the release builds. The purpose of assert() and _DEBUG is to not include them in release builds.It may be timing in a multi thread system, extra memory available for an out of bounds array read, or even the CPU being kept busy and heating up or avoiding yielding to some other program.
In examples 2, 3 and 4 the author explains what's wrong with the code and why it's a bad use of assert(). In example 1 though it's just called silly. What's wrong with that one?
You can read an asset in the form
I assert that _ will never be true
The style shown is saying I assert that false will never be true
And the message for the assert failing will be in a similar formatI feel that some programmers don't understand the actual semantic meaning of the word "assert", they just use it as an opaque key word meaning "check this", or something.
To me, it should be possible to read an assert almost like English, i.e.
assert(handle != INVALID_HANDLE);
can be read like "assert that the handle isn't invalid", i.e. is valid. Hm. I'm not stating this very clearly, sorry.Example 2 is just bad.
In example 3 some people compile with exceptions turned off. Asserting on new isn't a problem. Also, "The assert is supposed to check for bad code, not check errors" -- well new returning NULL would be bad code :) Also, in general, if malloc fails asserting is usually your best option, it's basically impossible without heroic efforts to recover from malloc failing, as almost anything you might do in recovery might try another mallocing!
Also, example 4 is (in my opinion) fine. I often 'assert' in programs when I have no idea what else to do. Asserting is certainly better than the alternative of just carrying on in a bad state, and fixing up the problem might be hard (I notice there is no suggested "fix" here).
Also, many of these comments related back to the original code by 'Satoshi', which makes the final comment, about 1x and 10x programmers hilarious: Yes, of course Satoshi was a '1x' programmer, how date we let them near the bitcoin source code, imagine how much better it would have been without them...
Asserts and other error handling (exceptions) have different semantics. Disabling asserts says "I believe this code has no bugs", not so unreasonable for a stable release. Disabling exceptions says "I believe nothing unexpected will ever happen", which is several notches crazier.
I suppose I could make up a new function, called say 'check', which basically did exactly the same thing as assert. But why bother? assert is already there and does what I want.
If there's no way to continue, you should also be ending the program in production builds, probably with a prettier error message.
It's arguably a point about style. The original code saved the effort of typing "assert()" twice but the granularity of exactly which condition failed the assertion is lost. E.g., a MSVC error will show granularity of line# but not the subexpression[1].
So there's a benefit of improved error reporting if the programmer wraps each conditional with its own assert().
[1] https://www.google.com/search?q=c%2B%2B+assert+error&source=...
> More generally, though, it shows why there's a difference between 1x and 10x programmers.
While I agree that some of the examples are impropriate, I think OP has generalized the issue too far. I don't believe knowing how to use assert properly has much contribution to productivity in programming.
It's a symptom of the problem, not the cause.
It demonstrates that they don't really understand the code they are writing, and it's that attitude and approach to programming that has a contribution to productivity.
That doesn't make him a good programmer. In fact it's entirely possible to be a brilliant cryptographer but only an average programmer.
Knowing where you are will help you progress. Believing that you are good while being bad has the only effect that you will not do anything to improve so you will stay bad. Is that what you want?
I agree that self-evaluation and recognition of inferior practices will help one progress, but the article would be more effective if the author was less condemning.