Jump to page: 1 24  
Page
Thread overview
John Regehr on "Use of Assertions"
Sep 01, 2018
Walter Bright
Sep 01, 2018
Guillaume Boucher
Sep 01, 2018
Walter Bright
Sep 02, 2018
Walter Bright
Sep 09, 2018
John Carter
Sep 09, 2018
John Carter
Sep 11, 2018
Neia Neutuladh
Sep 05, 2018
Timon Gehr
Sep 06, 2018
Walter Bright
Sep 08, 2018
Timon Gehr
Sep 02, 2018
Jonathan M Davis
Sep 02, 2018
John Colvin
Sep 03, 2018
Jonathan M Davis
Sep 03, 2018
John Colvin
Sep 02, 2018
Trass3r
Sep 03, 2018
Trass3r
Sep 05, 2018
Walter Bright
Sep 03, 2018
Meta
Sep 05, 2018
Meta
Sep 05, 2018
H. S. Teoh
Sep 07, 2018
Trass3r
Sep 09, 2018
Jonathan M Davis
Sep 05, 2018
Michael
Sep 05, 2018
H. S. Teoh
Sep 05, 2018
Timon Gehr
September 01, 2018
https://blog.regehr.org/archives/1091

As usual, John nails it in a particularly well-written essay.

"ASSERT(expr)
Asserts that an expression is true. The expression may or may not be evaluated.
If the expression is true, execution continues normally.
If the expression is false, what happens is undefined."

Note the "may or may not be evaluated." We've debated this here before. I'm rather pleased that John agrees with me on this. I.e. the optimizer can assume the expression is true and use that information to generate better code, even if the assert code generation is turned off.
September 01, 2018
On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright wrote:
> Note the "may or may not be evaluated." We've debated this here before. I'm rather pleased that John agrees with me on this.
>
> I.e. the optimizer can assume the expression is true and use that information to generate better code, even if the assert code generation is turned off.

You only read what you want to hear or what?

His essay is built up in a way where he shows two opposing interpretations of
asserts.  Assertions as "bug detectors" or as "optimizer hints".  He then
discusses which one of those is the better one.  The quote you gave is the
definition from a proponent of the "optimizer hint" camp and not necessarily what
John agrees with.

His conclusion in the essay is that in general it makes sense to have assertions
enabled even in release builds because a slightly worse performance is worth it
to have more robust programs and he has backed this up by a lot of examples.

Furthermore, he wrote a follow-up post about "assume"
(https://blog.regehr.org/archives/1096).  Assume seems to be what you think
assert is, but there is actually a *huge* difference.

> We assert a condition when we believe it to be true in every non-buggy
> execution of our program, but we want to be notified if this isn’t the case. In
> contrast, we assume a condition when our belief in its truth is so strong that
> we don’t care what happens if it is ever false. In other words, while
> assertions are fundamentally pessimistic, assumptions are optimistic.

So no, John doesn't agree with you on this *at all*.

September 01, 2018
On 9/1/2018 3:23 PM, Guillaume Boucher wrote:
> On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright wrote:
>> Note the "may or may not be evaluated." We've debated this here before. I'm rather pleased that John agrees with me on this.
>>
>> I.e. the optimizer can assume the expression is true and use that information to generate better code, even if the assert code generation is turned off.
> 
> You only read what you want to hear or what?
> 
> His essay is built up in a way where he shows two opposing interpretations of
> asserts.  Assertions as "bug detectors" or as "optimizer hints". He then
> discusses which one of those is the better one.  The quote you gave is the
> definition from a proponent of the "optimizer hint" camp and not necessarily what
> John agrees with.
> 
> His conclusion in the essay is that in general it makes sense to have assertions
> enabled even in release builds because a slightly worse performance is worth it
> to have more robust programs and he has backed this up by a lot of examples.

He says:

"Therefore, the compiler should feel free to optimize the program under the assumption that the asserted condition holds. Although this might be what we want — in fact it would be really cool if adding assertions made our code faster rather than slower — it’s not an interpretation that is universally useful. As developers, we might want to count on a certain kind of behavior when an assertion fails."

"not ... universally useful" is not quite not agreeing at all.


> Furthermore, he wrote a follow-up post about "assume"
> (https://blog.regehr.org/archives/1096).  Assume seems to be what you think
> assert is, but there is actually a *huge* difference.
> 
>> We assert a condition when we believe it to be true in every non-buggy
>> execution of our program, but we want to be notified if this isn’t the case. In
>> contrast, we assume a condition when our belief in its truth is so strong that
>> we don’t care what happens if it is ever false. In other words, while
>> assertions are fundamentally pessimistic, assumptions are optimistic.
> 
> So no, John doesn't agree with you on this *at all*.

I don't interpret it that way. Disabling runtime assert checking turns them into assumes. John is implying asserts should never be disabled.

September 01, 2018
On 09/01/2018 07:54 PM, Walter Bright wrote:
> On 9/1/2018 3:23 PM, Guillaume Boucher wrote:
>> On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright wrote:
>>> 
>>> [John agrees with me.]
>>
>> [No, he doesn't.]
> 
> [Yea-huh, he does.]
> 

You're both wrong. ;) Or actually, you're both right...

There's a section with the following heading:

   "Are Assertions Enabled in Production Code?"

First sentence of that section:

   "This is entirely situational."

One point for "John agrees with Walter."

HOWEVER, Walter has also expressed that a program should never continue after an assert failure. The concluding text of the same section:

   "[...rather interesting counterexample from NASA/Mars...] The question of whether it is better to stop or keep going when an internal bug is detected is not a straightforward one to answer."

One point for "John disagrees with Walter."
September 01, 2018
On 09/01/2018 08:44 PM, Nick Sabalausky (Abscissa) wrote:
> 
> You're both wrong. ;) Or actually, you're both right...
> 

That said, it IS a very interesting, well-written article.
September 01, 2018
On 09/01/2018 08:44 PM, Nick Sabalausky (Abscissa) wrote:
> 
>     "Are Assertions Enabled in Production Code?"
>     "This is entirely situational."
>     "The question of whether it is better to stop or keep going when an internal bug is detected is not a straightforward one to answer."


All in all, John is very non-committal about the whole thing.
September 01, 2018
On 9/1/2018 5:47 PM, Nick Sabalausky (Abscissa) wrote:
> All in all, John is very non-committal about the whole thing.

He probably got tired of arguing about it :-)
September 01, 2018
On Saturday, September 1, 2018 2:15:15 PM MDT Walter Bright via Digitalmars- d wrote:
> https://blog.regehr.org/archives/1091
>
> As usual, John nails it in a particularly well-written essay.
>
> "ASSERT(expr)
> Asserts that an expression is true. The expression may or may not be
> evaluated. If the expression is true, execution continues normally.
> If the expression is false, what happens is undefined."
>
> Note the "may or may not be evaluated." We've debated this here before. I'm rather pleased that John agrees with me on this. I.e. the optimizer can assume the expression is true and use that information to generate better code, even if the assert code generation is turned off.

Personally, my concern about letting the compiler optimize based on assertions has to do with whether it violates @safe. IMHO, it defeats the purpose of @safe if adding an assertion can result in @system code due to optimizations. I'm fine with it optimizing so long as the optimizations will not result in @safe code becoming @system in the case where the assertion would have failed if it were compiled in. If @safe allows @system optimizations than it isn't actually @safe, because while we don't want assertions to ever turn out to be false, they sometimes do turn out to be false, and if they're not compiled in, it's not going to be caught. That then is obviously a bug, but at least it isn't one that's going to corrupt memory (at least if it's in @safe code), but if the compiler is allowed to optimize based on the assertion to the point that the code could corrupt memory if the assertion would have failed, then that's a serious problem and a total violation of the promises made by @safe. And actually, it can't add @system optimizations even in @system code, because that completely defeats the ability of the programmer to verify the code for @safety in order to use @trusted.

If the compiler can add @safe optimizations based on assertions, then that's fine with me (though I know that some others don't agree), but they have to be @safe even when the assertion would have failed if it were compiled in. If they're ever @system, then @safe isn't actually @safe.

- Jonathan M Davis



September 02, 2018
On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright wrote:
> Note the "may or may not be evaluated." We've debated this here before. I'm rather pleased that John agrees with me on this.

It shouldn't allow side-effects then though.
https://run.dlang.io/is/P6VnYd

Also a common source of bugs in C.
September 02, 2018
On Sunday, 2 September 2018 at 02:32:31 UTC, Jonathan M Davis wrote:
> On Saturday, September 1, 2018 2:15:15 PM MDT Walter Bright via Digitalmars- d wrote:
>> https://blog.regehr.org/archives/1091
>>
>> As usual, John nails it in a particularly well-written essay.
>>
>> "ASSERT(expr)
>> Asserts that an expression is true. The expression may or may not be
>> evaluated. If the expression is true, execution continues normally.
>> If the expression is false, what happens is undefined."
>>
>> Note the "may or may not be evaluated." We've debated this here before. I'm rather pleased that John agrees with me on this. I.e. the optimizer can assume the expression is true and use that information to generate better code, even if the assert code generation is turned off.
>
> Personally, my concern about letting the compiler optimize based on assertions has to do with whether it violates @safe. IMHO, it defeats the purpose of @safe if adding an assertion can result in @system code due to optimizations. I'm fine with it optimizing so long as the optimizations will not result in @safe code becoming @system in the case where the assertion would have failed if it were compiled in. If @safe allows @system optimizations than it isn't actually @safe, because while we don't want assertions to ever turn out to be false, they sometimes do turn out to be false, and if they're not compiled in, it's not going to be caught. That then is obviously a bug, but at least it isn't one that's going to corrupt memory (at least if it's in @safe code), but if the compiler is allowed to optimize based on the assertion to the point that the code could corrupt memory if the assertion would have failed, then that's a serious problem and a total violation of the promises made by @safe. And actually, it can't add @system optimizations even in @system code, because that completely defeats the ability of the programmer to verify the code for @safety in order to use @trusted.
>
> If the compiler can add @safe optimizations based on assertions, then that's fine with me (though I know that some others don't agree), but they have to be @safe even when the assertion would have failed if it were compiled in. If they're ever @system, then @safe isn't actually @safe.
>
> - Jonathan M Davis

I believe asserts are the general case of which bounds checking is a specific instance. @safe code is only @safe if bounds-checking is enabled for @safe.

void foo(int[] a) @safe
{
    a[0] = 1;
}

is only really guaranteed safe if a bounds check is done, because [] is a valid array for a caller to pass.

void foo(int[] a) @safe
{
    assert(a.length == 1);
    a[0] = 1;
}

if asserts can be used as guarantees for the optimiser even when removed, this code is only @safe when asserts are enabled (because otherwise the bounds checks would be elided as they are guaranteed to pass).

So, essentially we just have to treat asserts like bounds checks and @safe will work as expected.


P.S.

// assert
debug assert(cond, msg);

// assume
assert(cond, msg);
« First   ‹ Prev
1 2 3 4