August 02, 2010
Mafi:
> If you want a NullPointerException as part of your program flow, you can use enforce() (in std.contracts I think). I don't think catching a NullPointerException in a big code block where you don't know which dereferencing should fail is good style.

enforce() is not a panacea (panchrest); as far as I know DMD doesn't inline any function that contains enforce(). So sometimes an assert() is better, especially if it's inside a contract (precondition, etc). DesignByConstrac-style programming is not something that just happens, you have to train yourself for some time for it.

Bye,
bearophile
August 02, 2010
On 8/2/10 10:33 AM, bearophile wrote:
> Mafi:
>> If you want a NullPointerException as part of your program flow, you can
>> use enforce() (in std.contracts I think). I don't think catching a
>> NullPointerException in a big code block where you don't know which
>> dereferencing should fail is good style.
>
> enforce() is not a panacea (panchrest); as far as I know DMD doesn't inline any function that contains enforce(). So sometimes an assert() is better, especially if it's inside a contract (precondition, etc). DesignByConstrac-style programming is not something that just happens, you have to train yourself for some time for it.
>
> Bye,
> bearophile

The problem isn't how to check it on a case-by-case basis, there are plenty of ways to check that a given pointer is non-null. The problem is debugging _unexpected_ null dereferences, for which a NPE or its equivalent is very helpful, a segfault is _not_.

Sorry, didn't mean to reopen a can of worms, just wanted to be clear.

--
rwsims
August 02, 2010
On Monday, August 02, 2010 08:34:50 Jeffrey Yasskin wrote:
> That's good to know. Unfortunately, reading through a null pointer does cause undefined behavior: it's not a guaranteed segfault. Consider an object with a large array at the beginning, which pushes later members past the empty pages at the beginning of the address space. I don't suppose the D compiler watches for such large objects and emits actual null checks before indexing into them?

There are no null checks. When people have requested in the past that null checks be added (like you'd get in Java), Walter has indicated that he thought that there was no point to them because the OS takes care of them already by giving you a segfault. I'm not personally well-versed enough in exactly what goes on at the hardware or OS level to produce a segfault, so I can't say whether a segfault is absolutely guaranteed. It has been my understanding that it is.

As for indexing into an array, the array itself should be null or not. It has no size if it's null, so it makes no sense to talk about large arrays which are null. On top of that, bounds checking is usually done on arrays (off of the top of my head, I don't remember the exact circumstances under which it's removed, but it's almost always there), so you wouldn't be able to index past its end, and if it's an element of the array that you're dereferencing, then whether that element is null or not will determine whether it segfaults.

> > The pages that you're looking at there need to be updated for clarity.
> 
> Nice use of the passive voice. Who needs to update them? Is their source somewhere you or I could send a patch?

Submit a bug report to bugzilla: http://d.puremagic.com/issues/

- Jonathan M Davis
August 02, 2010
Ryan W Sims:
> The problem isn't how to check it on a case-by-case basis, there are plenty of ways to check that a given pointer is non-null. The problem is debugging _unexpected_ null dereferences, for which a NPE or its equivalent is very helpful, a segfault is _not_.

I don't know what NPE is, but if you program with DbC your nulls are very often found out by asserts, so you have assert errors (that show line number & file name) instead of segfaults.


> Sorry, didn't mean to reopen a can of worms, just wanted to be clear.

When people that discuss are polite there is no problem in reopening the can now and then :-)

Bye,
bearophile
August 02, 2010
On 08/02/2010 11:27 PM, bearophile wrote:
> Ryan W Sims:
>> The problem isn't how to check it on a case-by-case basis, there are
>> plenty of ways to check that a given pointer is non-null. The problem is
>> debugging _unexpected_ null dereferences, for which a NPE or its
>> equivalent is very helpful, a segfault is _not_.
>
> I don't know what NPE is, but if you program with DbC your nulls are very often found out by asserts, so you have assert errors (that show line number&  file name) instead of segfaults.

Null Pointer Exception! However, I agree with getting segfaults from them. Otherwise, you will be tempted to use the exception handling mechanisms to catch null pointer exceptions, which is a bad thing.

I also agree with the notion of using DbC to find nulls.

What I really wish for is non-nullable types, though. Maybe in D3... :P
August 02, 2010
Jonathan M Davis:
> As for indexing into an array, the array itself should be null or not. It has no size if it's null, so it makes no sense to talk about large arrays which are null.

Technically dynamic arrays in D are represented with a 2-word struct that contains a pointer and length. So empty dynamic arrays are two zero words. In D there is also the literal [] that in my opinion is better to represent an empty array than just "null":
http://d.puremagic.com/issues/show_bug.cgi?id=3889

Bye,
bearophile
August 02, 2010
Pelle:

> Null Pointer Exception!

Ah, I see. I hate TLA (Three Letter Acronyms).


> What I really wish for is non-nullable types, though. Maybe in D3... :P

I think there is no enhancement request in Bugzilla about this, I will add one.

To implement this you have to think about the partially uninitialized objects too, this is a paper about it, given a class type T it defines four types (I think the four types are managed by the compiler only, the programmer uses only two of them, nullable class references and nonnullable ones):
http://research.microsoft.com/pubs/67461/non-null.pdf

If a language defaults to nonnullable references, then you can use this syntax:

class T {}
T nonnullable_instance = new T;
T? nullable_instance;

But now it's probably nearly impossible to make D references nonnullable on default, so that syntax can't be used. And I don't what syntax to use yet. Suggestions welcome.

Bye,
bearophile
August 02, 2010
> But now it's probably nearly impossible to make D references nonnullable on default, so that syntax can't be used. And I don't what syntax to use yet. Suggestions welcome.

One of the few ideas I have had is to use the @ suffix for this:

class T {}
T nullable_reference;
T@ nonnullable_reference = new T@();
struct S {}
S nullable_pointer;
S@ nonnullable_pointer = new S@();


(Beside nonnullable class references/pointers, another way to catch bugs that I miss in D are the ranged integers of ObjectPascal/Ada. Walter doesn't like them, I think he thinks they are a failed idea, but I don't agree and I don't remember why he thinks so.)

Bye,
bearophile
August 02, 2010
On 08/03/2010 12:02 AM, bearophile wrote:
> Pelle:
>> What I really wish for is non-nullable types, though. Maybe in D3... :P
>
> I think there is no enhancement request in Bugzilla about this, I will add one.

I think there has been, at least this has been discussed on the newsgroup.

> To implement this you have to think about the partially uninitialized objects too, this is a paper about it, given a class type T it defines four types (I think the four types are managed by the compiler only, the programmer uses only two of them, nullable class references and nonnullable ones):
> http://research.microsoft.com/pubs/67461/non-null.pdf
>
> If a language defaults to nonnullable references, then you can use this syntax:
>
> class T {}
> T nonnullable_instance = new T;
> T? nullable_instance;
>
> But now it's probably nearly impossible to make D references nonnullable on default, so that syntax can't be used. And I don't what syntax to use yet. Suggestions welcome.
>
> Bye,
> bearophile

That is a good syntax indeed. What is also needed is a way of conditionally getting the reference out of the nullable.

I think delight uses something like this:

T? nullable;
if actual = nullable:
    actual.dostuff;

I think a good thing would be NonNull!T, but I haven't managed to create one. If this structure exists and becomes good practice to use, maybe we can get the good syntax in D3. In 20 years or so :P
August 02, 2010
Pelle:
> I think a good thing would be NonNull!T, but I haven't managed to create one. If this structure exists and becomes good practice to use, maybe we can get the good syntax in D3. In 20 years or so :P

Maybe we are talking about two different things, I was talking about nonnull class references/pointers, you seem to talk about nullable values :-) Both can be useful in D, but they are different things.
Nullable values are simpler to design, they are just wrapper structs that contain a value plus a boolean, plus if you want some syntax sugar to manage them with a shorter syntax.

Bye,
bearophile