Null references redux

Jeremie Pelletier jeremiep at gmail.com
Sat Sep 26 19:59:02 PDT 2009


Yigal Chripun wrote:
> On 27/09/2009 00:59, Jeremie Pelletier wrote:
>> Jarrett Billingsley wrote:
>>> On Sat, Sep 26, 2009 at 5:29 PM, Jeremie Pelletier
>>> <jeremiep at gmail.com> wrote:
>>>
>>>> I actually side with Walter here. I much prefer my programs to crash on
>>>> using a null reference and fix the issue than add runtime overhead
>>>> that does
>>>> the same thing. In most cases a simple backtrace is enough to
>>>> pinpoint the
>>>> location of the bug.
>>>
>>> There is NO RUNTIME OVERHEAD in implementing nonnull reference types.
>>> None. It's handled entirely by the type system. Can we please move
>>> past this?
>>>
>>>> Null references are useful to implement optional arguments without any
>>>> overhead by an Optional!T wrapper. If you disallow null references what
>>>> would "Object foo;" initialize to then?
>>>
>>> It wouldn't. The compiler wouldn't allow it. It would force you to
>>> initialize it. That is the entire point of nonnull references.
>>
>> How would you do this then?
>>
>> void foo(int a) {
>> Object foo;
>> if(a == 1) foo = new Object1;
>> else if(a == 2) foo = Object2;
>> else foo = Object3;
>> foo.doSomething();
>> }
>>
>> The compiler would just die on the first line of the method where foo is
>> null.
>>
>> What about "int a;" should this throw an error too? Or "float f;".
>>
>> What about standard pointers? I can think of so many algorithms who rely
>> on pointers possibly being null.
>>
>> Maybe this could be a case to add in SafeD but leave out in standard D.
>> I wouldn't want a nonnull reference type, I use nullables just too often.
> 
> with current D syntax this can be implemented as:
> 
> void foo(int a) {
>   Object foo = (a == 1) ? new Object1
>              : (a == 2) ? Object2
>              : Object3;
>   foo.doSomething();
> }
 >
> The above agrees also with what Denis said about possible uninitialized 
> variable bugs.
> 
> in D "if" is the same as in C - a procedural statement.
> I personally think that it should be an expression like in FP languages 
> which is safer.
 >
> to reinforce what others have said already:
> 1) non-null references *by default* does not affect nullable references 
> in any way and does not add any overhead. The idea is to make the 
> *default* the *safer* option which is one of the primary goals of this 
> language.
> 2) there is no default value for non-nullable references. you must 
> initialize it to a correct, logical value *always*. If you resort to 
> some "default" value you are doing something wrong.
> 
> btw, C++ references implement this idea already. functions that return a 
> reference will throw an exception on error (Walter's canary) while the 
> same function that returns a pointer will usually just return null on 
> error.
> 
> segfaults are *NOT* a good mechanism to handle errors. An exception 
> trace gives you a whole lot more information about what went wrong and 
> where compared to a segfault.

This is something for the runtime or the debugger to deal with. My 
runtime converts access violations on windows or segfaults on linux into 
exception objects, which unwind all the way down to main where it 
catches into the unhandled exception handler (or crash handler) and I 
get a neat popup with a "hello, your program crashed at this point, here 
is a backtrace with resolved symbols and filenames along with current 
registers and loaded modules, would you like a cup of coffee while you 
solve the problem?". I sent that crash handler to D.announce last week too.

The compiler won't be able to enforce *every* nonnull reference and 
segfaults are bound to happen, especially with casting. While it may 
prevent most of them, any good programmer would too, I don't remember 
the last time I had a segfault on a null reference actually.

I can see what the point is with nonnull references, but I can also see 
its not a bulletproof solution. ie "Object foo = cast(Object)null;" 
would easily bypass the nonnull enforcement, resulting in a segfault the 
system is trying to avoid.

What about function parameters, a lot of parameters are optional 
references, which are tested and then used into functions whose 
parameters aren't optional. It would result in a lot of casts, something 
that could easily confuse people and easily generate segfaults.

Alls I'm saying is, nonnull references would just take the issue from 
one place to another. Like Walter said, you can put a gas mask to ignore 
the room full of toxic gas, but that doesn't solve the gas problem in 
itself, you're just denyinng it exists. Then someday you forget about 
it, remove the mask, and suffocate.

Jeremie



More information about the Digitalmars-d mailing list