C `restrict` keyword in D

Moritz Maxeiner via Digitalmars-d digitalmars-d at puremagic.com
Tue Sep 5 14:25:00 PDT 2017


On Tuesday, 5 September 2017 at 18:32:34 UTC, Johan Engelen wrote:
> On Monday, 4 September 2017 at 21:23:50 UTC, Moritz Maxeiner 
> wrote:
>> On Monday, 4 September 2017 at 17:58:41 UTC, Johan Engelen 
>> wrote:
>>>
>>> (The spec requires crashing on null dereferencing, but this 
>>> spec bit is ignored by DMD and LDC, I assume in GDC too.
>>> Crashing on `null` dereferencing requires a null-check on 
>>> every dereferencing through an unchecked pointer, because 0 
>>> might be a valid memory access, and also because 
>>> ptr->someDataField is not going to lookup address 0, but 
>>> 0+offsetof(someDataField) instead, e.g. potentially 
>>> addressing a valid low address at 1000000, say.)
>>
>> It's not implemented as compiler checks because the "actual" 
>> requirement is "the platform has to crash on null dereference" 
>> (see the discussion in/around [1]). Essentially: "if your 
>> platform doesn't crash on null dereference, don't use D on it 
>> (at the very least not @safe D)".
>
> My point was that that is not workable. The "null dereference" 
> is a D language construct, not something that the machine is 
> doing.

While "null dereference" is a language construct "null" is 
defined as actual address zero (like it's defined in C/C++ by 
implementation) and dereference means r/w from/to that virtual 
memory address, it is something the machine does: Namely, memory 
protection, because the page for address 0 is (usually) not 
mapped (and D requires it to not be mapped for @safe to work), 
accessing it will lead to a page fault, which in turn leads to a 
segmentation fault and then program crash.

> It's ridiculous to specify that reading from address 1_000_000 
> should crash the program, yet that is exactly what is specified 
> by D when running this code (and thus null checks need to be 
> injected in many places to be spec compliant):
>
> ```
> struct S {
>   ubyte[1_000_000] a;
>   int b;
> }
> void main() {
>    S* s = null;
>    s.b = 1;
> }
> ```

In order to be spec compliant and correct a compiler would only 
need to inject null checks on dereferences where the size of the 
object being pointed to (in your example S.sizeof) is larger than 
the bottom virtual memory segment of the target OS (the one which 
no C compatible OS maps automatically and you also shouldn't map 
manually).
The size of that bottom segment, however, is usually 
_deliberately_ large precisely so that buggy (C) programs crash 
on NULL dereference (even with structures as the above), so in 
practice, unless you invalidate assumptions about expected 
maximum structure sizes made by the OS, null dereferences can be 
assumed to crash.


More information about the Digitalmars-d mailing list