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.

Reply via email to