On Friday, October 13, 2017 11:26:54 kdevel via Digitalmars-d-learn wrote: > 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?
Essentially, though talking about conforming usually has to do with spec. In both C/C++ and D, if you use an assertion, you're saying that if the assertion fails, then the logic in your code is faulty, and there is a bug in your program. With C/C++, it may not be codified that the compiler understands that, but the meaning is the same. If the assertion is compiled out but would have failed, then your program is in an invalid state and will do who-knows-what. By definition, you're screwed. Your program is doing something that you have said should never happen. How screwed you actually are can vary considerably, and if all it does is print out the value and never use it again, then you're not very screwed, but that also means that it was a rather odd assertion (though you're obviously doing that here as an example and not something that someone would normally do). Because D's compiler does understand what assert means, it is allowed to optimize based on that fact. So, it _can_ generate code based on the assumption that the assertion succeeded, which can increase how screwed you are if the assertion is compiled out but would have failed, but your program is in an invalid state either way, because you've asserted that something is true when it isn't and thus indicated that if it isn't true, there is a bug in your program, and its logic is wrong. And as soon as the logic in your program is wrong, then it's not going to behave correctly. It's just a question of how badly behaved it will be. So, we can talk about the behavior being undefined if the assertion would have failed on the basis that the compiler could generate optimized code that assumes that the assertion succeeded and thus do weirder things than it would have done if the code hadn't been optimized that way, but as far as the language is concerned, it's undefined behavior due to the simple fact that you've asserted that something is true which isn't. You yourself have stated that something must be true for your program to be valid, and it isn't true. As long as the assertions are compiled in, then the fact that the logic in your program was invalid is caught, whereas if they're not compiled in, then it's not caught. But if the asserted condition is false, then your program is wrong either way. - Jonathan M Davis