John Regehr on "Use of Assertions"

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Sep 9 06:27:52 UTC 2018


On Saturday, September 8, 2018 5:31:43 PM MDT Nick Sabalausky (Abscissa) via 
Digitalmars-d wrote:
> On 09/05/2018 03:35 PM, Meta wrote:
> > I think the only sane way to use asserts as an
> > optimization guide is when the program will abort if the condition does
> > not hold. That, to me, makes perfect sense, since you're basically
> > telling the compiler "This condition must be true past this assertion
> > point, because otherwise program execution will not continue past this
> > point". You're ensuring that the condition specified in the assert is
> > true by definition. Not having that hard guarantee but still using
> > asserts as an optimization guide is absolutely insane, IMO.
>
> I'd certainly agree with this.
>
> Frankly though, I've always found `-release` itself to be a horrible
> thing to use, and I never go anywhere near it. It's a classic case of
> premature optimization, pure and simple - and a dangerous one at that.
>
> IMO the only time an assert should be omitted (note: *an* assert, none
> of this module-level granularity stuff), even in release mode, is when
> you can verify that leaving the assert in would be prohibitively
> expensive: For example, frequent integrity checks on large trees, or
> bounds-checking an inner-loop of a performance-critical codepath.
>
> Removing an assert in release mode is exactly the same as declaring
> "This part can't ever fail, so let's not worry about 'What happens if it
> does fail?'" (if you're THAT certain, why did you write the assert there
> in the first place???). TBH, I'm very surprised that Walter would ever
> be in favor of it.

I think that it's all about how you look at it. If you look at assertions as
a way to abort your program because things are so broken that it's too
dangerous to continue, then yeah, removing them is dangerous.

However, if you look at them purely as a debugging tool to help you catch
problems during develepment, that it's no more dangerous to remove
assertions and have the code continue if they would have failed than it is
for any other part of the program to be wrong and continue to operate.
There's nothing special about the code being wrong when an assertion fails
except that it's a case where you put an actual test for it. That code is
broken or not regardless of whether the assertion is actually there. The
assertion is just helping to catch the bug.

I think that that it's this duality of thinking here that's causing a lot of
the problems. Assertions are usually presented as a way to catch bugs during
development (and thus will be removed in production) and _not_ as a way to
catch errors severe enough to abort the program in production. And so a lot
of programmers are going to use them purely as a debugging tool. So, for
assertions to then be used to kill the program in production arguably
doesn't match what they were intended for at all, and when you're adding
assertions with the understanding that they're going to be removed in
production, you're a lot more likely to do stuff like use an assertion to
verify that sort sorted a list correctly, which would be insane to do in
production, whereas if you were using assertions specifically to indicate
that the program _must_ abort if the condition isn't true - even in
production - then you're going to be thinking completely differently about
what you test in assertions.

IIRC, Weka has different types of assertions to differentiate between these
two approaches - one for the cases which absolutely must not happen in
production, and one that's purely for catching problems during developement.
And really, I think that that's probably the right approach.

For many programs, leaving assertions in during production is just going to
needlessly slow the program down, and if the developers know that an
assertion is going to be left in production, they're a lot less likely to
use assertions. On the other hand, there are definitely cases where testing
a conditition is critical enough that you want that test to always be in the
code and for it to abort on failure even in production.

So, maybe what we should do here is take a page from Weka's playbook and add
a function that does something like check a condition and then assert(0) if
it's false and not try to say that assertions should always be left in
production. Sure, someone can choose to not use -relase and leave them in,
but that's often not how assertions are actually used (e.g. last time I
checked std.algorithm's sort really does check that the range is sorted with
an assertion).

- Jonathan M Davis





More information about the Digitalmars-d mailing list