February 03, 2014
On Sunday, 2 February 2014 at 23:55:48 UTC, Andrei Alexandrescu wrote:
> On 2/2/14, 3:44 PM, Timon Gehr wrote:
>> On 02/03/2014 12:09 AM, Andrei Alexandrescu wrote:
>>>
>>> A front-end pass could replace the dead dereference with a guard that
>>> asserts the reference is not null.
>>
>> I don't think this would be feasible. (The front-end pass would need to
>> simulate all back-end passes in order to find all the references that
>> might be proven dead.)
>
> Well I was thinking of a backend-specific assertion directive. Worst case, the front end could assign to a volatile global:
>
> __vglobal = *p;
>
>
> Andrei

As far as the backend is concerned, dereferencing and assigning to a volatile are 2 distinct operations.
February 03, 2014
On 2/2/14, 5:47 PM, deadalnix wrote:
> On Sunday, 2 February 2014 at 23:55:48 UTC, Andrei Alexandrescu wrote:
>> On 2/2/14, 3:44 PM, Timon Gehr wrote:
>>> On 02/03/2014 12:09 AM, Andrei Alexandrescu wrote:
>>>>
>>>> A front-end pass could replace the dead dereference with a guard that
>>>> asserts the reference is not null.
>>>
>>> I don't think this would be feasible. (The front-end pass would need to
>>> simulate all back-end passes in order to find all the references that
>>> might be proven dead.)
>>
>> Well I was thinking of a backend-specific assertion directive. Worst
>> case, the front end could assign to a volatile global:
>>
>> __vglobal = *p;
>>
>>
>> Andrei
>
> As far as the backend is concerned, dereferencing and assigning to a
> volatile are 2 distinct operations.

No matter. The point is the dereference will not be dead to the optimizer.

Andrei
February 03, 2014
On Monday, 3 February 2014 at 03:49:20 UTC, Andrei Alexandrescu wrote:
> No matter. The point is the dereference will not be dead to the optimizer.
>
> Andrei

I see. But how would you add these without adding thousand of them all over the place ?
February 03, 2014
I'm not sure what to do about null references. One of my ideas is that some type of Exception or Throwable object should be thrown when accessing null pointer instead of getting SEGFAULT. In this way programmer can handle exception at application level, get some information about problem and may be sometimes it's possible to recover. At the current state OS send SEGFAULT message and I can't even get some info where is the source of problem. It's the most annoying thing about null references for me.

Of course we can provide some wrapper struct for reference that will check reference for null and throw Exception if it's null. Another way is provide it at compiler level. The third variant is forbid null references somehow at all (currently it's possible via wrapper). As I thinking today for me 2nd variant is prefered. Providing Error when reading null variable will reduce code bloat.

But it's only my point of view. Since I dont know anything about compiler implementation it's interesting to know what do you think of this.
February 03, 2014
On 2/3/2014 12:00 AM, Uranuz wrote:
> At the current state OS send SEGFAULT message and I can't
> even get some info where is the source of problem.

1. Compile with symbolic debug info on (-g switch)

2. Run under a debugger, such as gdb

3. When it seg faults, type:

   bt

and it will give you a "backtrace", i.e. where it faulted, and the functions that are on the stack.
February 03, 2014
On Saturday, 1 February 2014 at 18:58:11 UTC, Andrei Alexandrescu wrote:
> It also became clear that a library solution would improve things but cannot compete with a language solution.
I'm really shocked! This issue must be way bigger than I think, if even Andrei is asking for a language solution instead of a library one! :o)

> Bottom line: a language change for non-null references is on the table. It will be an important focus of 2014.
That's interesting news. Null dereferences can be real annoying, sometimes.
February 03, 2014
On Monday, February 03, 2014 00:56:05 Walter Bright wrote:
> On 2/3/2014 12:00 AM, Uranuz wrote:
> > At the current state OS send SEGFAULT message and I can't even get some info where is the source of problem.
> 
> 1. Compile with symbolic debug info on (-g switch)
> 
> 2. Run under a debugger, such as gdb
> 
> 3. When it seg faults, type:
> 
>     bt
> 
> and it will give you a "backtrace", i.e. where it faulted, and the functions that are on the stack.

I recall there being a change to druntime such that it would print a backtrace for you if you hit a segfault, but it doesn't seem to work when I write a quick test program which segfaults, so I'm not sure what happened to that. Certainly, I think that that solves the issue from the standpoint of the program simply printing out "segmentation fault" being too little info (since it would then print a stacktrace as well). But as long as that doesn't work, using gdb's the best way - and it has the advantage of letting you examine the program state at that point in time rather than just see the stacktrace.

- Jonathan M Davis
February 03, 2014
On 2/1/14, 7:14 AM, Jonathan M Davis wrote:
> In the general case, you can only catch it at compile time if you disallow it
> completely, which is unnecessarily restrictive. Sure, some basic cases can be
> caught, but unless the code where the pointer/reference is defined is right
> next to the code where it's dereferenced, there's no way for the compiler to
> have any clue whether it's null or not.

This is not true. It's possible to do this, at least for the case where you dereference a variable or an object's field. See this:

http://crystal-lang.org/2013/07/13/null-pointer-exception.html

February 03, 2014
On 2/3/14, 5:56 AM, Walter Bright wrote:
> On 2/3/2014 12:00 AM, Uranuz wrote:
>> At the current state OS send SEGFAULT message and I can't
>> even get some info where is the source of problem.
>
> 1. Compile with symbolic debug info on (-g switch)
>
> 2. Run under a debugger, such as gdb
>
> 3. When it seg faults, type:
>
>     bt
>
> and it will give you a "backtrace", i.e. where it faulted, and the
> functions that are on the stack.

You keep missing the point that when the segfault happens you might have no idea how to reproduce it. You don't even know where it happens. So it's not that easy to reach point 3.

If a null access raises an exception, you immediately get the backtrace and that can help you understand why it happened.
February 03, 2014
On Monday, February 03, 2014 09:30:32 Ary Borenszweig wrote:
> On 2/1/14, 7:14 AM, Jonathan M Davis wrote:
> > In the general case, you can only catch it at compile time if you disallow it completely, which is unnecessarily restrictive. Sure, some basic cases can be caught, but unless the code where the pointer/reference is defined is right next to the code where it's dereferenced, there's no way for the compiler to have any clue whether it's null or not.
> 
> This is not true. It's possible to do this, at least for the case where you dereference a variable or an object's field. See this:
> 
> http://crystal-lang.org/2013/07/13/null-pointer-exception.html

In the _general_ case it is not possible. It's certainly possible within certain snippets of code - any obvious example being

int* i;
*i = 5;

but it's not possible for the compiler to know under all sets of circumstances. Something as simple as using a function's return value makes it so that it can't know. e.g.

int* i = foo();
*i = 5;

For it to know, it would have to examine the body of foo (which it doesn't necessarily have the code for under C's compilation model - which D uses), and even if it did that wouldn't be enough e.g.

int* foo()
{
    return "/etc/foo".exists ? new int : null;
}

The compiler could flag that as _possibly_ returning null and therefore the previous code _possibly_ dereferencing null, but it can't know for sure.

So, with full program analysis, it would certainly be possible to determine whether a particular pointer _might_ be null when it's dereferenced and flag that as a warning or error, but without full program analysis (which the compiler can't normally do with C's compilation model), you can't do that in most cases, and even with full program analysis, you can't always determine whether a pointer will definitively be null or not when it's dereferenced.

Crystal's compilation model may allow it to check a lot more code than C's does, allowing it to detect null dereferences in more cases, and it may very well simply error out when it detects that a pointer _might_ be null when it's dereferenced, but as I understand it, it's fundamentally impossible to determine at compile time under all circumstances whether a pointer will definitively be null or not (as evidenced by the body of foo above - the result depends entirely on runtime state).

- Jonathan M Davis