Is the following well defined and allowed?

Steven Schveighoffer schveiguy at yahoo.com
Fri Mar 2 14:39:32 UTC 2018


On 3/1/18 5:27 PM, ag0aep6g wrote:

> You're looking at the behavior of the compiled executable. Then it makes 
> sense to say that a program compiled with the checks has defined 
> behavior (throwing Errors) and a program without the checks does 
> something undefined (because the compiler manual doesn't say that 
> anything in particular is supposed to happen).

No, I'm looking at the source code.

At the very basic level, you have this:

assert(foo == 0);

Or whatever other condition you have. What this does is gives the 
compiler leeway to ASSUME foo is 0 at this point. It can make any number 
of optimizations assuming this. If foo is NOT equal to 0 at this point, 
then it is a program error, and the assumptions may cause bad things to 
happen.

When you compile in normal mode, this assert causes an Error to be 
thrown, before your code can do any damage.

When you compile without asserts, this causes undefined behavior.

The various switches and modes can say whether asserts or other checks 
are present or not, and if they are not, the compiler is going to 
execute your UB code with those wrong assumptions. But ONLY if the 
assert would have been false.

I extend this same treatment and logic to all checks: contracts, bounds 
checks, overlapping slice assign checks, etc. To me, they aren't any 
different than asserts. They aren't any different if they are in @safe 
code or @system code.

> That's not how I understand/use "undefined behavior". To me, it's the D 
> source code that can have "undefined behavior". When it does, the 
> program (as given in source code) is invalid and the compiler can do 
> whatever it wants with it. It may:
> 
> 1) reject the program statically, or it may
> 2) generate code that throws an Error at run time, or it may
> 3) generate code that does something arbitrary.
> 
> With that meaning of UB, out-of-bounds accesses and overlapping copies 
> have undefined behavior in @system code, but they have defined behavior 
> in @safe code.

By default, both @system and @safe code have bounds checks. So by 
default, it is defined behavior (an Error is thrown) regardless of the 
safety.

If you turn the checks off (through any means) then it becomes UB.

> In this interpetation, -noboundscheck switches DMD to a different 
> dialect of D. In that dialect, out-of-bounds accesses (and overlapping 
> copies, apparently) always have UB, in both @system and @safe code. That 
> defeats the purpose of @safe. Which is why I don't really care for that 
> dialect.

I agree, I think we should remove the option to disable bounds checks on 
@safe code, in any way. It's too dangerous. If you want performance that 
comes without bounds checks, use a trusted escape, or write system code.

-Steve


More information about the Digitalmars-d mailing list