April 14, 2005
Anders F Björklund wrote:
> Regan Heath wrote:
> 
>>>> 2) it decreases performance slightly since it has to do the null checks
>>>
>>>
>>> I'm somehow suspecting this the main reason it's the way it is.
>>
>>
>> So can't it be treated similarly to array bounds checks? only done if not  -release mode.
> 
> 
> I think Walter said he preferred the hardware to do the null pointer checks, even in the -release builds... (i.e. trap the hardware signal)
> 
> Thread: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/14342
> Walter: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/14440
> 
> And redefining == with objects seem to be totally out of the question.
> (i.e. making equality comparisions with null a legal/defined operation)
> 
> --anders

Hmm, why not make ==null or null== totally illegal in the first place? I mean, "if (a=func())" is illegal, and it can actually be what the user wanted; opCmp(null) is practically never what is wanted, so a compiler error should be issued and solve this without any special handling of ==.

Just my thoughts..


xs0
April 14, 2005
xs0 wrote:

> Hmm, why not make ==null or null== totally illegal in the first place?

They are now. Just not flagged at compile-time, but at run-time instead:
"If one or the other or both objects are null, an exception is raised."

Allowing '== null' was mostly to make it simpler to convert from C/Java,
or from using a "struct*" and then changing to using an Object instead ?
(although '==' has a different meaning for pointers and for references,
which is discussed in great detail in the other thread about '=='/'===')


It's mostly likely possible to have the D compiler catch these two
common errors, or perhaps have a "dlint" tool as a secondary option.

And having the compiler catch it, would probably be better than now too.
I was just discussing the alternative; of making it a legal operation ?


Note that the compiler can probably not catch the "dynamic" alternative,
such as when you have: "Object x,y; if (x == y) { ... }", and so on...

--anders
April 16, 2005
On Thu, 14 Apr 2005 13:27:17 +0200, Anders F Björklund <afb@algonet.se> wrote:
> Regan Heath wrote:
>
>>>> 2) it decreases performance slightly since it has to do the null checks
>>>
>>> I'm somehow suspecting this the main reason it's the way it is.
>>  So can't it be treated similarly to array bounds checks? only done if not  -release mode.
>
> I think Walter said he preferred the hardware to do the null pointer checks, even in the -release builds... (i.e. trap the hardware signal)
>
> Thread: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/14342
> Walter: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/14440

So we already have a null pointer exception, sort of, called Exception.

Next question, is there any reason to create and throw a spcific exception for this i.e. NullPtrException? I'm thinking "no" because what possible reason would an application have for catching that specifically?

However.. the error message is simply "Access Violation" with no file/line information. So, my suggestion is that in non -release builds i.e. builds in which array bounds and other checks are performed, the error message should read something like "Accessed null reference at file:line".

Regan
April 16, 2005
Regan Heath wrote:

> So we already have a null pointer exception, sort of, called Exception.

Yeah, "sort of", on Windows. The segfault catcher for Linux was:
http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/20190

> Next question, is there any reason to create and throw a spcific exception  for this i.e. NullPtrException? I'm thinking "no" because what possible  reason would an application have for catching that specifically?

Depends on if you want to separate exceptions on name, or on class ?
Also, "Access Violation" is a Windows term... It has other names too.

> However.. the error message is simply "Access Violation" with no file/line  information. So, my suggestion is that in non -release builds i.e. builds  in which array bounds and other checks are performed, the error message  should read something like "Accessed null reference at file:line".

Yeah, that was I thought too - in the original post / suggestion. But
Walter preferred the hardware solution. Besides, GDB shows the line:

# cat null.d
void main()
{
  int* p = null;
  *p = 0; // oops
}

# gdc -o null null.d
# gdc --version                               gdc (GCC) 3.3.5 (Apple patches from build 1495)
[...]
# ./null 

Bus error

# gdc -o null -g null.d
# gdb ./null
GNU gdb 5.3-20030128 (Apple version gdb-330.1)
[...]
Program received signal EXC_BAD_ACCESS, Could not access memory.
0x0000217c in _Dmain () at null.d:4
4         *p = 0; // oops
(gdb)

For debugging, I think I even *prefer* that over an anymous exception ?
(I'm not sure how you can get Windows debuggers to trap at the "*null")


But - the original question in this thread was whether "null == this"
should dereference null, or if it should simply be *defined* as false.

And it seems like the dereference/exception way is preferred by D :
Walter http://www.digitalmars.com/drn-bin/wwwnews?D/13854


So I consider this thread closed. AV/SEGV/BE is the designed behaviour.
Also, "this == null" doesn't do it *every* time. Just in some cases...

But it does make the pitfall for old java programmers all the greater.
(since "==" will not just be a little slower, but throw Exceptions...)

--anders
April 16, 2005
On Sat, 16 Apr 2005 10:15:14 +0200, Anders F Björklund <afb@algonet.se> wrote:
> Regan Heath wrote:
>
>> So we already have a null pointer exception, sort of, called Exception.
>
> Yeah, "sort of", on Windows. The segfault catcher for Linux was:
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/20190

I believe Walter intends to make sure that all D's features operate on all platforms that can support them.

>> Next question, is there any reason to create and throw a spcific exception  for this i.e. NullPtrException? I'm thinking "no" because what possible  reason would an application have for catching that specifically?
>
> Depends on if you want to separate exceptions on name, or on class ?
> Also, "Access Violation" is a Windows term... It has other names too.

True. However I was thinking about it from the other direction, assuming we call it something would you ever want to catch it? What would you do with it once you caught? There seems little point to catching it to me. Thus, a better error string is all I'd like.

>> However.. the error message is simply "Access Violation" with no file/line  information. So, my suggestion is that in non -release builds i.e. builds  in which array bounds and other checks are performed, the error message  should read something like "Accessed null reference at file:line".
>
> Yeah, that was I thought too - in the original post / suggestion. But
> Walter preferred the hardware solution.

As do I, for -release builds where performance is desire. However, while debugging I prefer a nice error message containing file and line number whenever possible.

> Besides, GDB shows the line:
>
> # cat null.d
> void main()
> {
>    int* p = null;
>    *p = 0; // oops
> }
>
> # gdc -o null null.d
> # gdc --version                                gdc (GCC) 3.3.5 (Apple patches from build 1495)
> [...]
> # ./null Bus error
>
> # gdc -o null -g null.d
> # gdb ./null
> GNU gdb 5.3-20030128 (Apple version gdb-330.1)
> [...]
> Program received signal EXC_BAD_ACCESS, Could not access memory.
> 0x0000217c in _Dmain () at null.d:4
> 4         *p = 0; // oops
> (gdb)
>
> For debugging, I think I even *prefer* that over an anymous exception ?
> (I'm not sure how you can get Windows debuggers to trap at the "*null")

An exception that prints file and line number is more useful. Beta testers are unlikely to be running the app in a debugger (in my experience).

> But - the original question in this thread was ..

I wasn't interested in the original question. Sorry for hijacking the thread.

Regan
April 18, 2005
"Anders F Björklund" <afb@algonet.se> wrote in message news:d3g9j9$2apd$2@digitaldaemon.com...
> I remember being somewhat surprised when it did not throw an exception but segfaulted instead,

Seg faulting is throwing an exception - it's just done by the hardware. You can even catch them:


int main()
{
    int* p;

    try
    {
       *p = 3;
    }
    catch (Object o)
    {
         printf("caught the exception: %.*s\n", o.toString());
    }
    return 0;
}

Running it gives:

    C:>test
    caught the exception: Access Violation


April 18, 2005
Walter wrote:

>>I remember being somewhat surprised when it did not throw
>>an exception but segfaulted instead,
> 
> Seg faulting is throwing an exception - it's just done by
> the hardware. You can even catch them:

It is, in the broad sense, I suppose... But I was more kinda
expecting a subclass of class Exception being thrown, rather
than a signal handler being invoked by the operating system.

Anyway, I thought we cleared all that up - way back then ?
(the solution being to add such handlers for other OS too)

> Running it gives:
> 
>     C:>test
>     caught the exception: Access Violation

Yeah, or:

$ ./test
Bus error

It depends a little on the platform... ;-)

But it seems like having "null == this" return false is out
of the question, so I will just leave this thread at that.

--anders
April 19, 2005
Anders F Björklund wrote:
> 
> But it seems like having "null == this" return false is out
> of the question, so I will just leave this thread at that.
> 
> --anders

Absolutely not out of the question:

I don't understand the difficulty here--this is the major obstacle in porting java code

I suggest walter does some syntactic sugar transformations here:
change
A==B
to
(A===null?(B===null):(B===null?false:A.opEqual(B)))

then if people don't want that overhead they can explicitly call A.opEqual(B);

and the beauty of this solution is that it keeps *all* working code in tact, yet it improves robustness of Java portation. And in addition there are NO performance implications (if you are in the know and this is the inner loop (why oh why are you using virtual functions then), use .opEqual

(unless it relies on that caught access violation garbage--in which case it wasn't working in the first place)
April 19, 2005
Daniel Horn wrote:

>> But it seems like having "null == this" return false is out
>> of the question, so I will just leave this thread at that.

> Absolutely not out of the question:

I just meant that just like a boolean type this has been suggested,
and rejected, for addition in the D language multiple times already ?

Arguing about the decision here, doesn't seem to make it more likely...
I guess someone just gets to write a book about it. "Imperfect D" ? ;-)

> I don't understand the difficulty here--this is the major obstacle in porting java code
> 
> I suggest walter does some syntactic sugar transformations here:
> change
> A==B
> to
> (A===null?(B===null):(B===null?false:A.opEqual(B)))
> 
> then if people don't want that overhead they can explicitly call A.opEqual(B);
> 
> and the beauty of this solution is that it keeps *all* working code in tact, yet it improves robustness of Java portation. And in addition there are NO performance implications (if you are in the know and this is the inner loop (why oh why are you using virtual functions then), use .opEqual

No argument there, and this was exactly my (rejected) suggestion too...
(usually, there is also a short path for "this is object" in opEquals)

But Walter thinks that comparing something (Object) with null is outside
the contract of '==', and thus should trigger an Exception to be thrown.

That it is a hardware signal trap that is throwing the Exception in
question, that is just an optimization - as far as I've understood it ?


For the time being, unless there is *major* shift in how things work
around here - this is just yet another big thing to be aware of in D. :(

See http://www.prowiki.org/wiki4d/wiki.cgi?ShortFrequentAnswers:

- Comparing an object reference like: "if (object == null)" will crash.
  You must use "if (object is null)"

- Checking for a key in an AA like: "if(array[key])" will create it if
  it's missing. You must use "if(key in array)"

The second being totally unrelated, except that it also traps up people
from outside regularly and is another frequent suggestion for change....

--anders


PS. I thought it could working something similar to this old suggestion:
http://cdsmith.twu.net/professional/java/pontifications/comparison.html
(it also suggests "inlining" '==' as '===', if both are of type Object?)
April 19, 2005
Anders F Björklund wrote:
> Daniel Horn wrote:
> 
>>> But it seems like having "null == this" return false is out
>>> of the question, so I will just leave this thread at that.
> 
> 
>> Absolutely not out of the question:
> 
> 
> I just meant that just like a boolean type this has been suggested,
> and rejected, for addition in the D language multiple times already ?
> 
> Arguing about the decision here, doesn't seem to make it more likely...
> I guess someone just gets to write a book about it. "Imperfect D" ? ;-)
> 
>> I don't understand the difficulty here--this is the major obstacle in porting java code
>>
>> I suggest walter does some syntactic sugar transformations here:
>> change
>> A==B
>> to
>> (A===null?(B===null):(B===null?false:A.opEqual(B)))
>>
>> then if people don't want that overhead they can explicitly call A.opEqual(B);
>>
>> and the beauty of this solution is that it keeps *all* working code in tact, yet it improves robustness of Java portation. And in addition there are NO performance implications (if you are in the know and this is the inner loop (why oh why are you using virtual functions then), use .opEqual
> 
> 
> No argument there, and this was exactly my (rejected) suggestion too...
> (usually, there is also a short path for "this is object" in opEquals)
> 
> But Walter thinks that comparing something (Object) with null is outside
> the contract of '==', and thus should trigger an Exception to be thrown.
> 
> That it is a hardware signal trap that is throwing the Exception in
> question, that is just an optimization - as far as I've understood it ?
> 
> 
> For the time being, unless there is *major* shift in how things work
> around here - this is just yet another big thing to be aware of in D. :(
> 
> See http://www.prowiki.org/wiki4d/wiki.cgi?ShortFrequentAnswers:
> 
> - Comparing an object reference like: "if (object == null)" will crash.
>   You must use "if (object is null)"

This is unfortunate, indeed.

One might say that creating gratuituous (and unobvious) traps for newcomers to a new language is not good for the language.

The only excuse for still having this would be some important consistency issue. Something akin to the many things where early C made some "conveniences" in syntax, resulting in 30 years of grief for mankind.

For the moment, though, I cannot see such a major excuse. (There might be one, but it would behoove Walter to explain it carefully.)

> - Checking for a key in an AA like: "if(array[key])" will create it if
>   it's missing. You must use "if(key in array)"

Same thing here.

If there is a good motivation for if(array[key]) silently inserting the key, then so be it. BUT THEN this should be VERY prominently in the documentation. AND with a proper explanation of the reason this is so.

     People can accept pretty much anything
       -- as long as they clearly see why.


> The second being totally unrelated, except that it also traps up people
> from outside regularly and is another frequent suggestion for change....
> 
> --anders
> 
> 
> PS. I thought it could working something similar to this old suggestion:
> http://cdsmith.twu.net/professional/java/pontifications/comparison.html
> (it also suggests "inlining" '==' as '===', if both are of type Object?)