Assert and undefined behavior

kdevel kdevel at vogtner.de
Fri Oct 13 11:26:54 UTC 2017


On Friday, 13 October 2017 at 02:22:24 UTC, Jonathan M Davis 
wrote:
> You've told it that i should never be 3 at that point and that 
> it's a bug if it is, and as such, it is free to assume that i 
> is never 3 after the assertion even if the assertion is 
> compiled out with -release - that is the only place that 
> undefined behavior may enter into it.

Thanks for the clarification! This is a difference to C where 
assert has only a diagnostic purpose. Disabling assertions in C 
(by setting NDEBUG) does AFAICS neither introduce undefined 
behavior nor is the compiler entitled to optimize code away based 
on the assertion. This C program

--- test.c
#include <stdio.h>
#define NDEBUG 1
#include <assert.h>
int main ()
{
    int i = 3;
    assert (i != 3);
    if (i == 3)
       printf ("%d\n", i);
    return 0;
}
---

is IMHO conforming and it is defined to print 3 in a conforming 
environment. The 'corresponding' D program

--- assert4.d
import std.stdio;
int main ()
{
    int i = 3;
    assert (i != 3);
    if (i == 3)
       writef ("%d\n", i);
    return 0;
}
---

is 'conforming' (but buggy) under non-release-D and 
'non-conforming' (because of the undefined behavior) otherwise. 
Is this judgement correct?

> If the compiler does an optimization based on the fact that i 
> isn't 3, and it is, and -release is used, then you could get 
> some weird behavior when the code reaches the lines after the 
> assertion - but by definition, you already have a bug if i is 
> 3, and your program in general is assuming that i isn't 3 at 
> that point, so you're going to get bad behavior either way.

I would like to make a clear distiction between "bug" or "bad 
behavior" on the one hand and "undefined behavior" on the other. 
"Bug" and "bad behavior" address the outcome of a computation 
while "undefined behavior" is an (abstract, formal) property of a 
piece of code with respect to a certain language specification.

> The fact that your assertion failed means that you have a logic 
> error in your program, and it is therefore in an invalid state 
> and will likely not behave correctly.

Under non-release-D the program is perfectly valid and behaves 
exactly as expected. In relase-D it makes no sense to discuss if 
the state of program is valid or if the program behaves 
correctly, since it is non-conforming because of the undefined 
behavior.

(...)

> On a side note, I would point out that talking about "debug 
> mode" with D gets annoyingly ambiguous, because that kind of 
> implies the -debug flag, which has nothing to do with 
> assertions and which actually can be used in conjunction with 
> -release (all -debug does is enable debug{} blocks), which is 
> why I try to avoid the term debug mode - though I assume that 
> you meant when -release isn't used, since that's often what 
> folks mean.

Agreed.


More information about the Digitalmars-d-learn mailing list