digitalmars.D - How to check for null references
- =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= (9/9) Aug 27 2007 Hi all!
- Carlos Santander (6/22) Aug 27 2007 Since you're learning D, questions like this one are better suited for t...
- =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= (3/29) Aug 27 2007 Thank you! I'll direct the basic questions to the learn-newsgroup from n...
- Jascha Wetzel (4/18) Aug 27 2007 the "==" operator can be overloaded and D implicitly dereferences
- Tim Healey (10/10) Aug 27 2007 Use 'is' to test for null:
- =?ISO-8859-1?Q?Hans-Eric_Gr=f6nlund?= (2/17) Aug 27 2007
- Robert Fraser (3/23) Aug 27 2007 This one seems to trip up a lot of new users. Is there some way (short o...
- Nathan Reed (4/8) Aug 27 2007 How about just issuing a warning if 'null' is on either side of an == si...
- Robert Fraser (7/17) Aug 27 2007 I guess my problem is this (taken from object.d):
- Sean Kelly (5/25) Aug 27 2007 opEquals needs to be in Object because it is used by the AA code.
- Daniel Keep (58/66) Aug 27 2007 Just a note: I just re-read what you said and realised you meant it
-
Stewart Gordon
(11/20)
Aug 28 2007
- Nathan Reed (10/18) Aug 27 2007 It probably should be removed, or replaced by a throw, but this doesn't
- Bill Baxter (4/27) Aug 27 2007 About the opEquals return value:
- Sean Kelly (3/7) Aug 27 2007 It's a historic issue regarding code generation and should be changed.
Hi all! I'm trying to learn D, mostly by trial and error, and I keep tripping over the smallest rocks. This time the pebble is: How can I gracefully check if an object reference is null? I get an access violation if I try this and the reference (o) is null: if (o == null) {...} Is this a bug in DMD (I use the stable 1.x version) or did I miss something obvious? Best regards Hans-Eric Grönlund Software Developer, Project Manager, Freelance Journalist http://www.hans-eric.com/
Aug 27 2007
Hans-Eric Grönlund escribió:Hi all! I'm trying to learn D, mostly by trial and error, and I keep tripping over the smallest rocks. This time the pebble is: How can I gracefully check if an object reference is null? I get an access violation if I try this and the reference (o) is null: if (o == null) {...} Is this a bug in DMD (I use the stable 1.x version) or did I miss something obvious?Use: if (o is null) {...}Best regards Hans-Eric Grönlund Software Developer, Project Manager, Freelance Journalist http://www.hans-eric.com/Since you're learning D, questions like this one are better suited for the D.learn newsgroup. -- Carlos Santander Bernal
Aug 27 2007
Thank you! I'll direct the basic questions to the learn-newsgroup from now on. /Hans-Eric Carlos Santander Wrote:Hans-Eric Grönlund escribió:Hi all! I'm trying to learn D, mostly by trial and error, and I keep tripping over the smallest rocks. This time the pebble is: How can I gracefully check if an object reference is null? I get an access violation if I try this and the reference (o) is null: if (o == null) {...} Is this a bug in DMD (I use the stable 1.x version) or did I miss something obvious?Use: if (o is null) {...}Best regards Hans-Eric Grönlund Software Developer, Project Manager, Freelance Journalist http://www.hans-eric.com/Since you're learning D, questions like this one are better suited for the D.learn newsgroup. -- Carlos Santander Bernal
Aug 27 2007
Hans-Eric Grönlund wrote:Hi all! I'm trying to learn D, mostly by trial and error, and I keep tripping over the smallest rocks. This time the pebble is: How can I gracefully check if an object reference is null? I get an access violation if I try this and the reference (o) is null: if (o == null) {...} Is this a bug in DMD (I use the stable 1.x version) or did I miss something obvious? Best regards Hans-Eric Grönlund Software Developer, Project Manager, Freelance Journalist http://www.hans-eric.com/the "==" operator can be overloaded and D implicitly dereferences pointers to structs/classes, therefore the identity operator "is" and "!is" has to be used.
Aug 27 2007
Use 'is' to test for null: if ( o is null ) { ... } From http://www.digitalmars.com/d/expression.html#IdentityExpression : For class objects, identity is defined as the object references are for the same object. Null class objects can be compared with is. The run-time error you got is because the program was essentially executing this: if ( o.opEquals( null ) ) { ... } This is intended behavior, though I'm not finding the right spec page to link you to at the moment.
Aug 27 2007
Thank you Tim (and the others that pointed this out)! I had a feeling there'd be a simple answer. Tim Healey Wrote:Use 'is' to test for null: if ( o is null ) { ... } From http://www.digitalmars.com/d/expression.html#IdentityExpression : For class objects, identity is defined as the object references are for the same object. Null class objects can be compared with is. The run-time error you got is because the program was essentially executing this: if ( o.opEquals( null ) ) { ... } This is intended behavior, though I'm not finding the right spec page to link you to at the moment.
Aug 27 2007
This one seems to trip up a lot of new users. Is there some way (short of making it huge, red, and flashing) to make this somehow more obvious o the D webpage. I'm sure it trips up quite a few people who already know the rule, too (I don't do too much D work, and I've already been bitten once or twice). I think the best way might be to issue a compiler error if an object doesn't have an opEquals() overload instead of providing a default implementation in object (like for all the other operator overloads). That would break a lot of existing code, though, but the compiler would help fix it rather than having it break silently. Hans-Eric Grönlund Wrote:Thank you Tim (and the others that pointed this out)! I had a feeling there'd be a simple answer. Tim Healey Wrote:Use 'is' to test for null: if ( o is null ) { ... } From http://www.digitalmars.com/d/expression.html#IdentityExpression : For class objects, identity is defined as the object references are for the same object. Null class objects can be compared with is. The run-time error you got is because the program was essentially executing this: if ( o.opEquals( null ) ) { ... } This is intended behavior, though I'm not finding the right spec page to link you to at the moment.
Aug 27 2007
Robert Fraser wrote:This one seems to trip up a lot of new users. Is there some way (short of making it huge, red, and flashing) to make this somehow more obvious o the D webpage. I'm sure it trips up quite a few people who already know the rule, too (I don't do too much D work, and I've already been bitten once or twice). I think the best way might be to issue a compiler error if an object doesn't have an opEquals() overload instead of providing a default implementation in object (like for all the other operator overloads). That would break a lot of existing code, though, but the compiler would help fix it rather than having it break silently.How about just issuing a warning if 'null' is on either side of an == sign? Thanks, Nathan Reed
Aug 27 2007
Nathan Reed Wrote:Robert Fraser wrote:I guess my problem is this (taken from object.d): int opEquals(Object o) { return cast(int)(this is o); } All object.opEquals() is doing is invoking "is", so it's kind of tricking people who don't know/remember that == doesn't test for identity and theoretically (it'd probably be inlined, but still) slowing down code. What's the point? Seems like it'd be better all around to get rid of it entirely.This one seems to trip up a lot of new users. Is there some way (short of making it huge, red, and flashing) to make this somehow more obvious o the D webpage. I'm sure it trips up quite a few people who already know the rule, too (I don't do too much D work, and I've already been bitten once or twice). I think the best way might be to issue a compiler error if an object doesn't have an opEquals() overload instead of providing a default implementation in object (like for all the other operator overloads). That would break a lot of existing code, though, but the compiler would help fix it rather than having it break silently.How about just issuing a warning if 'null' is on either side of an == sign? Thanks, Nathan Reed
Aug 27 2007
Robert Fraser wrote:Nathan Reed Wrote:opEquals needs to be in Object because it is used by the AA code. However, it could be changed to simply throw an exception, thus requiring users to override it. SeanRobert Fraser wrote:I guess my problem is this (taken from object.d): int opEquals(Object o) { return cast(int)(this is o); } All object.opEquals() is doing is invoking "is", so it's kind of tricking people who don't know/remember that == doesn't test for identity and theoretically (it'd probably be inlined, but still) slowing down code. What's the point? Seems like it'd be better all around to get rid of it entirely.This one seems to trip up a lot of new users. Is there some way (short of making it huge, red, and flashing) to make this somehow more obvious o the D webpage. I'm sure it trips up quite a few people who already know the rule, too (I don't do too much D work, and I've already been bitten once or twice). I think the best way might be to issue a compiler error if an object doesn't have an opEquals() overload instead of providing a default implementation in object (like for all the other operator overloads). That would break a lot of existing code, though, but the compiler would help fix it rather than having it break silently.How about just issuing a warning if 'null' is on either side of an == sign? Thanks, Nathan Reed
Aug 27 2007
Sean Kelly wrote:[snip] opEquals needs to be in Object because it is used by the AA code. However, it could be changed to simply throw an exception, thus requiring users to override it. SeanJust a note: I just re-read what you said and realised you meant it should throw an exception in all cases. I thought you meant if you were trying to compare to null (duh). I'm not sure if I'm for or against that idea, but it would certainly fix the problem. Especially if the error was "Use the is operator, and read the documentation!" :P (Although, that doesn't help us if they haven't worked out they need to use 'new', but you can't have everything :P) -- Daniel Just because I put a lot[1] of effort into it, here's what I was *going* to write: [1] When I say "a lot" I mean "had to write, compile, debug and disassemble a test program immediately after waking up." I deserve a *medal* for that! module nullobj; class Foo { int opEquals(Object other) { throw new Exception("AARGH, GOODBAI KRUUL WURLD!"); } } void main() { Foo foo; bool foundit = cast(bool)(foo == null); } -----dmd nullobj && nullobjError: Access Violation See, it already throws an exception! :P Let's see what happens when we disassemble the code in main: nullobj.d:11 void main() 0040204c: c8080000 enter 0x8, 0x0 nullobj.d:13 Foo foo; 00402050: 31c0 xor eax, eax 00402052: 8945f8 mov [ebp-0x8], eax nullobj.d:14 bool foundit = cast(bool)(foo == null); 00402055: 50 push eax 00402056: 8b08 mov ecx, [eax] 00402058: ff5114 call dword near [ecx+0x14] 0040205b: f7d8 neg eax 0040205d: 19c0 sbb eax, eax 0040205f: f7d8 neg eax 00402061: 8845fc mov [ebp-0x4], al 00402064: 31c0 xor eax, eax nullobj.obj 00402066: c9 leave 00402067: c3 ret Ok, look at the call and the lines above it. That's the line where we call opEquals. But notice how we're doing it? We're calling it by using one of the vtable functions, stored as an offset from the start of the object. But the object's null, so when we try to work out where the opEquals function is... BOOM. So yes, we *can* already have opEquals throw an exception if the object's null. It just has to be a segfault, since if the object's null, we can't find opEquals. As an aside, I love ddbg ^_^
Aug 27 2007
"Sean Kelly" <sean f4.ca> wrote in message news:favmpt$fkr$1 digitalmars.com...Robert Fraser wrote:<snip>To serve as a default equality test for classes that don't implement their own.All object.opEquals() is doing is invoking "is", so it's kind of tricking people who don't know/remember that == doesn't test for identity and theoretically (it'd probably be inlined, but still) slowing down code. What's the point? Seems like it'd be better all around to get rid of it entirely.opEquals needs to be in Object because it is used by the AA code. However, it could be changed to simply throw an exception, thus requiring users to override it.What would the point of this be? I don't see there being any such thing as there being a class with no concept of equality, not even that of being one and the same object. Besides, as at least one person has already said, this does nothing for the original subject: the null reference checking problem. Stewart.
Aug 28 2007
Robert Fraser wrote:I guess my problem is this (taken from object.d): int opEquals(Object o) { return cast(int)(this is o); } All object.opEquals() is doing is invoking "is", so it's kind of tricking people who don't know/remember that == doesn't test for identity and theoretically (it'd probably be inlined, but still) slowing down code. What's the point? Seems like it'd be better all around to get rid of it entirely.It probably should be removed, or replaced by a throw, but this doesn't change the fact that if you use == to test for null references, you get a runtime error and there's no indication of the problem at compile time. A warning would be helpful (or even an error, since AFAIK there's no situation where writing 'o == null' is the right thing to do). (OT) by the way, is there a reason opEquals returns int? I'm sure people have pointed this out before, but bool would seem to be more natural. Thanks, Nathan Reed
Aug 27 2007
Nathan Reed wrote:Robert Fraser wrote:I guess my problem is this (taken from object.d): int opEquals(Object o) { return cast(int)(this is o); } All object.opEquals() is doing is invoking "is", so it's kind of tricking people who don't know/remember that == doesn't test for identity and theoretically (it'd probably be inlined, but still) slowing down code. What's the point? Seems like it'd be better all around to get rid of it entirely.It probably should be removed, or replaced by a throw, but this doesn't change the fact that if you use == to test for null references, you get a runtime error and there's no indication of the problem at compile time. A warning would be helpful (or even an error, since AFAIK there's no situation where writing 'o == null' is the right thing to do).(OT) by the way, is there a reason opEquals returns int? I'm sure people have pointed this out before, but bool would seem to be more natural.About the opEquals return value: http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/OperatorOverloading --bb
Aug 27 2007
Nathan Reed wrote:(OT) by the way, is there a reason opEquals returns int? I'm sure people have pointed this out before, but bool would seem to be more natural.It's a historic issue regarding code generation and should be changed. Sean
Aug 27 2007