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.


Reply via email to