View mode: basic / threaded / horizontal-split · Log in · Help
September 27, 2009
Re: Null references redux
On 27/09/2009 00:59, Jeremie Pelletier wrote:
> Jarrett Billingsley wrote:
>> On Sat, Sep 26, 2009 at 5:29 PM, Jeremie Pelletier
>> <jeremiep@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.
September 27, 2009
Re: Null references redux
Sat, 26 Sep 2009 15:49:06 -0700, Walter Bright thusly wrote:

> I used to work at Boeing designing critical flight systems. Absolutely
> the WRONG failure mode is to pretend nothing went wrong and happily
> return default values and show lovely green lights on the instrument
> panel.

Basically if there is only one way the system can operate correctly, your 
approach is to catch errors on runtime (segfaults) until a later 
iteration of the program development turns out to work correctly or well 
enough. Meanwhile there are several buggy revisions of the program in the 
development process.

The idea behind non-nullable types and other contracts is to catch these 
errors on compile time. Sure, the code is a bit harder to write, but it 
is safe and never segfaults. The idea is to minimize the amount of 
runtime errors of all sorts. That's also how other features of statically 
typed languages work.
September 27, 2009
Re: Null references redux
Sun, 27 Sep 2009 02:04:06 +0200, Yigal Chripun thusly wrote:

> 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.

Indeed, especially since in the case of D half of the userbase has a 
broken linker (optlink) and the other half has a broken debugger (gdb). I 
much rather write non-segfaulting applications in a language without 
debugger than buggy crap and debug it with the world's best debugger.
September 27, 2009
Re: Null references redux
Sat, 26 Sep 2009 18:38:56 -0500, Andrei Alexandrescu thusly wrote:

> Your code in
> Phobos reflects that perspective. In the RegExp class, for example, you
> very often define a variable at the top of a long function and
> initialize it halfway through it. I trivially replaced such code with
> the correct code that defines symbols just where they're needed.

Maybe Walter has not yet transitioned from the good olde Pascal/C style 
programming to the C++/D/Java style?
September 27, 2009
Re: Null references redux
On 27/09/2009 00:51, Walter Bright wrote:
> grauzone wrote:
>> Walter Bright wrote:
>>> It is exactly analogous to a null pointer exception. And it's darned
>>> useful.
>>
>> On Linux, it just generates a segfault. And then you have no idea
>> where the program went wrong. dmd outputting incorrect debugging
>> information (so you have troubles using gdb or even addr2line) doesn't
>> really help here.
>
> Then the problem is incorrect dwarf output, not null pointers.
>
>
>> Not so useful.
>
> It's *still* far more useful than generating corrupt output and
> pretending all is ok.

An exception trace is *far* better than a segfault and that does not 
require null values.

what's better?
a)
 auto a = new Class; // returns null (out of memory)
 a.foo = 5; // segfault since a is null

OR
b)
 auto a = new Class; // throws an out of memory exception
 a.foo = 5; // doesn't even reach here

no one here argues for option c where a holds garbage and the program 
generates corrupt output.
September 27, 2009
Re: Null references redux
Andrei Alexandrescu wrote:
> Walter Bright wrote:
>> Even forcing an explicit initializer doesn't actually solve the 
>> problem - my experience with such features is programmers simply 
>> insert any old value to get the code to pass the compiler, even 
>> programmers who know it's a bad idea do it anyway.
> 
> I think you're starting to be wrong at the point where you don't realize 
> that many bugs come from references that people have forgotten to 
> initialize. Once you acknowledge those, you will start to realize that a 
> reference that must compulsively be initialized is valuable.

The problem is it's worse to force people to provide an initializer. 
Most of the time that will work out ok, but the one silent bad value 
producing silent bad output overbalances all of it. Null pointer 
dereferences do not produce bad output that can be overlooked.

It isn't a theoretical problem with providing bad initializers just to 
shut the compiler up. I have seen it in the wild every time some manager 
required that code compile without warnings and the compiler warned 
about no initializer.

I'm very much a fan of increasing D's ability to detect and head off 
common mistakes, but it's really easy to tip into seducing programmers 
into writing bad code in order to avoid an overly nagging compiler.

There's the other problem of how to represent an "empty" value. You have 
to create a special object that then you have to either test for 
explicitly, or that has member functions that throw. You're no better 
off with that, and arguably worse off.


> You think from another perspective: you strongly believe that *most* of 
> the time you can't or shouldn't initialize a reference. Your code in 
> Phobos reflects that perspective. In the RegExp class, for example, you 
> very often define a variable at the top of a long function and 
> initialize it halfway through it. I trivially replaced such code with 
> the correct code that defines symbols just where they're needed.

That style doesn't reflect anything more than my old C habits which 
require declarations before any statements. I know it's bad style and do 
it less and less over time.
September 27, 2009
Re: Null references redux
language_fan wrote:
> Maybe Walter has not yet transitioned from the good olde Pascal/C style 
> programming to the C++/D/Java style?

Heh, there's still a Fortran influence in my code <g>.
September 27, 2009
Re: Null references redux
Jason House wrote:
> Walter Bright Wrote:
> 
>> Denis Koroskin wrote:
>>> On Sat, 26 Sep 2009 22:30:58 +0400, Walter Bright 
>>> <newshound1@digitalmars.com> wrote:
>>>> D has borrowed ideas from many different languages. The trick
>>>> is to take the good stuff and avoid their mistakes <g>.
>>> 
>>> How about this one:
>>> 
>> http://sadekdrobi.com/2008/12/22/null-references-the-billion-dollar-mistake/
>> 
>> 
>>> 
>>> 
>>> :)
>> 
>> I think he's wrong.
>> 
>> Getting rid of null references is like solving the problem of dead
>>  canaries in the coal mines by replacing them with stuffed toys.
>> 
>> It all depends on what you prefer a program to do when it
>> encounters a program bug:
> 
> What do you define as a bug?

The program doing something it was not deliberately programmed to do.
September 27, 2009
Re: Null references redux
language_fan wrote:
> The idea behind non-nullable types and other contracts is to catch these 
> errors on compile time. Sure, the code is a bit harder to write, but it 
> is safe and never segfaults. The idea is to minimize the amount of 
> runtime errors of all sorts. That's also how other features of statically 
> typed languages work.


I certainly agree that catching errors at compile time is preferable by 
far. Where I disagree is the notion that non-nullable types achieve 
this. I've argued extensively here that they hide errors, not fix them.

Also, by "safe" I presume you mean "memory safe" which means free of 
memory corruption. Null pointer exceptions are memory safe. A null 
pointer could be caused by memory corruption, but it cannot *cause* 
memory corruption.
September 27, 2009
Re: Null references redux
Walter Bright wrote:
> Andrei Alexandrescu wrote:
>> Walter Bright wrote:
>>> Even forcing an explicit initializer doesn't actually solve the 
>>> problem - my experience with such features is programmers simply 
>>> insert any old value to get the code to pass the compiler, even 
>>> programmers who know it's a bad idea do it anyway.
>>
>> I think you're starting to be wrong at the point where you don't 
>> realize that many bugs come from references that people have forgotten 
>> to initialize. Once you acknowledge those, you will start to realize 
>> that a reference that must compulsively be initialized is valuable.
> 
> The problem is it's worse to force people to provide an initializer. 

You're not forcing. You just change the default. Really, it's *exactly* 
the same deal as with = void that you're so happy about.

Andrei
1 2 3 4 5 6 7 8 9
Top | Discussion index | About this forum | D home