- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Admin
You do if you want to find out if it is actually in the database... But that's not the way to do it!
Admin
Admin
That is what I was thinking. I just wanted to make sure I wasn't missing something else, because I know I'd written similar crap when I first started.
Admin
Smut [image]
Admin
Yikes, how the hell did I forget that you could cast a null pointer to the class and call its methods? I've been writing C and assembly for too long...
(and I don't really know Java)
Admin
"I invented the term Object-Oriented and I can tell you I did not have C++ in mind." -- Alan Kay
Admin
If he meant "if (this==NULL)" then it's definitly a wtf.
Admin
Having assert(this) might make sense(But I would really like my compiler to always do that in debug mode. Having to add the code to all my methods by 'hand is' is stupid).
but having if(!this) return false is a wtf because it transform a 'fast fail' into something that return an arbitrary value, thus causing a hell for debugging later.
Or maybe the code is supposed to 'work correctly' when called on a null pointer, but that would be its own wtf(And would depend on the exact way the compiler would generate code).
Admin
Here's the thing:
In very very very early C++ days, there were no static methods. So if you wanted to define one, you'd have to do it as a free function -- but if you did, you lost access to any private static members. So instead, the idiom for a static method was to do ((Foo *)(0))->blah(). If you look at sufficiently old books, this is still used in some places.
Admin
The problem with the !this is not the test, it's what's done about it. On occasion it might make sense to return false if called on a null but that certainly shouldn't be the normal result. The desired result generally should be to die.
I could believe this started from somebody getting blamed for crashes due to someone else's code and they did this so the blowups wouldn't be in their code and then it somehow became standard practice.
Admin
That depends on your definition of "possible". The code will compile all right, so by one definition it's "possible". At runtime, however, you've just entered undefined territory, and it may well NOT be "possible" to make that call at run time. Worse, it's legal for that call to now format your hard drive (yeah, I'm being pedantic, as no implementation is going to do this, but the point stands).
Many implementations allow that call, so it's debatable whether or not checking if "this == 0" is ever something to consider doing. I think most would side on the act being a WTF, though, especially if you do anything other than cause some sort of immediate failure (and returning a value, even an error code, doesn't fit that definition). The GetSafeHwnd() is a WTF, though it was there for a reason. Always doing a "return false" is a WTF, and there can't be a defensible reason.
Admin
np: Prefuse 73 - Half Up Front (Everything She Touched Turned Ampexian)
Admin
Wrong.
Link* Link::insert(Link* n) { if (n==0) return this; if (this==0) return n; ... }
from Bjarne Stroustrup, "Programming: Principles and Practice Using C++", p. 605.
Admin
What are you talking about? NULL and 0 are synonymous in C++.
Admin
Although,
is even better, as it avoids pointlessly creating extra Boolean object instances.
Admin
What if confirm() returns FILE_NOT_FOUND?
Admin
Admin
This is even more amazing if you understand autoboxing and notice the operations the compiler will add in. The final result is something like
wow.
Admin
What's the difference? I would have thought they both created exactly one Boolean instance (but I don't have any great level of understanding of how Java's boxing works).
Admin
What if the code in question is part of an engine management system? Do you want your car to just die while you're merging into rush hour traffic? Even if the class in quesion is CRearWiperControl and the function is EnableMotor()? return false works for me here.
I've written a number of Windows services in my career, and 'just die' is never an option. (Same would apply to a *nix daemon process). The service/daemon should keep running, even it it hits an 'impossible' error processing a single request.
Even in a simple web app, 'just die' isn't very elegant. The customer sees a blank page. Support has no clue what went wrong. Developers dismiss the bug report because they can't reproduce it.
if(!this) return false; certainly is a WTF, but not because it's too defensive. It's not defensive enough. As already mentioned, you really want an assert here so you can catch these things during development. And throwing an exception is probably better than return false, assuming you have an exception handler in place somewhere up the stack. And make sure you log it if you can. assert is great but it disappears in your release build. Customers run release builds.
So, to be pedantic: bool foo() { assert(this); if(!this) Log("NULL pointer passed to foo()); if(!this) return false; // or throw new SomeException() }
And since this is C++, you can bury all those details in some sort of VERIFYTHIS() macro if you are so inclined.
Admin
I see what you did there.
Admin
The original test included inp.equals("true") so probably inp is of type String.
Boolean answer = inp.equals("true"); // autoboxing
or even better
Boolean answer = inp.equalsIgnoreCase("true");
Admin
Boolean.valueOf doesn't create any objects. The Boolean class has two static instances of Boolean (Boolean.TRUE and Boolean.FALSE). Boolean.valueOf returns one of the already existing objects.
Admin
Some C++ compilers, if told not to use exceptions, will not return a null pointer if new fails - that function is explicitly defined to return an exception on error. It mainly comes up if you're overriding the memory allocation / deallocation functions for some reason, eg to track leaks or to deliberately corrupt memory or simulate tight constraints to make the code more robust.
What tends to happen, at least under gcc 4, is that you end up with the stupid compiler calling an object's constructor even on a failure, because it expects you to be throwing an exception to stop it instead. But if you've got a product that requires legacy platform support then you generally can't use exceptions because they're not supported by all older C++ compilers. Not to mention that they make it harder to read code, and much more difficult to isolate things like memory leaks if you're not careful.
Thus there are perfectly legitimate situations where checking that the this pointer isn't null is necessary. Probably putting it everywhere is overkill but it certainly won't be something the optimiser will remove.
Admin
I guess you mean that NULL is defined as 0 (not always true), which is, I hope, done for a reason. Defining NULL, not it being equal to 0.
Why not just say zero-pointer instead of null-pointer? Why invent the term null at all?
Anyways, the wtf is knowing what the (pre)compiler makes of it and then applying that knowledge in the code, completely screwing any related human language agreement/convention.
Admin
The "if (!this) return false" case is checking for method calls on null pointers. It's paranoid, probably eliminates some optimizations, and doesn't work when multiple inheritance is involved.
Admin
Admin
Clause 4.10 of the current C++ standard says
In fact, mostly the same holds for modern versions of C. Clause 6.3.2.3 of the current C standard says Your claim applies only in pre-ANSI standard versions of C.Admin
You're right. There's no "extra" instance. Just the one the reference of which is assigned to the variable.
You only have the choice between...
* ...creating the instance explicitly, as it always has been in Java (with new) and assigning its reference to a variable
* ...performing some function (valueOf, equals, equalsIgnoreCase) assigning a primitive value to an object reference(!) and let Java's implicit often spurned autoboxing create the object and assign its reference to the variable
* ...deciding which code is more readable and quicker
Admin
Throwing an exception IS a means of dying. Maybe something up the chain will handle it. Anything that MUST keep on going (your embedded systems example) certainly will handle it at the top.
However, in general it's a lot better for a program to terminate than to continue on with obviously bad instructions.
Admin
Admin
Nope, the C++ standard explicitly states that the constant expression 0 is a null pointer. And that is why NULL is, and will always be, #define'd as 0.
Where it gets funky is that a null pointer may not necessarily correspond to the address zero. But if you assign zero to a pointer, that pointer becomes a null pointer. Even if this operation is implemented by storing a non-zero address into the pointer. And that is why it is not called a zero-pointer. As far as the language is concerned, it is not "a pointer to the address zero", but "a pointer that points nowhere".
That quote has always annoyed me. It is a fundamental misunderstanding to assume that C++ is *meant* to be an object-oriented language. He might as well have said that he didn't have LISP, Haskell or Prolog in mind when he invented the term. It'd be true, and pretty uninformative in either case.I think one of C++'s biggest strengths is that it is not a strict OOP language.
Admin
myclass* p; p->function();
A common mistake. Now since pointers are not automatically initialised to 0, the "this" in the function has a random value. It doesn't help to test for !this.
Admin
The best defense is a good offense!
Admin
I'm pretty sure he had LISP in mind, since the first object systems were written in LISP.
C++ was meant to be an object oriented language with support for a templating type system. You can read all about it on Bjarne's homepage.
http://www.research.att.com/~bs/oopsla.pdf
The ironically titled paper "Why C++is not just an Object-Oriented Programming Language" explains why. Most of the features Bjarne says make C++ "not purely object oriented" are now considered object-oriented. From the abstract:
Which of the features Bjarne pointed out as not being OO do you not consider OO? Keep in mind you can write "C-style" code in any language. Even Haskell, a purely functional language.
Generic programming is merely quantification over classes.
Admin
While it may be true that !this does not catch wild pointers (which are not guaranteed to be null), you should be initializing your pointers explicitly anyway (via myclass* p=NULL;, myclass* p=new myclass(<insert ctor args here>);, myclass* p=SomeFunctionThatReturnsAMyclassPointer();, etc.).
Admin
I wrote "not always true" to indicate that in some versions NULL is defined as 0, and in some as a void* cast blabla something. It all means the same essentially. I know.
Actually, I don't care what it is defined as, and neither should anybody. As long as I know that I can use NULL to test for null-pointers.
But hey, I'm probably alone this....
So to recap:
Lets agree on pointers that point nowhere to call them null-pointers and not zero-pointers. Hell, let's make a define for NULL as well.
And then, let's NOT use the define for NULL, but 0 in the code. Heck, it saves us 4 keypresses everytime!
Hooray, we made things a lot more clearer now.
Admin
3!
Admin
Admin
Of course it might have been more helpful had it simply thrown an exception instead of masking the problem.
Admin
Admin
To decrement a NULL pointer, it helps to think of pointers as unsigned. So they don't have -1. They can be 0xFFFF, 0xFFFFF or 0xFFFFFFFF, depending on the memory model. Or even more Fs, if you have 64 bit addres space. (What's the name of the 64 bit memory model? It must be bigger than "huge".)
Addendum (2009-05-17 05:43): Oh, I see I misread your second question. If you have a long pointer to the physical address 1, decrementing it would result in the physical address 0. That's not so hard.
On the other hand, you have to keep the environment in mind. For instance, your C compiler might start to complain loudly if you want to make a pointer to an address that is not on a doubleword boundary. Or decrementing it would result in 0xFFFFFFFD. (MSVC 8 does the latter, but has no problems with the former.)
Admin
In C++, unlike in C, in no case is NULL permitted to be defined as a void*. This is explicitly stated in the standard.
18.1 Types, para 4: "The macro NULL is an implementation-defined C++ null pointer constant in this International Standard (4.10).180)
The reason for this is that defining NULL as ((void*)0) would break a large proportion of existing code, since such simple statements as char* ptr = NULL; would break.
Admin
Admin
On most platforms that any programmer will ever meet, a null pointer is the same thing as a pointer to the address zero. It's just that the C standard does not guarantee that this will be the case, so an implementation that did it differently could still claim to implement ISO C.
A hypothetical scenario where this might be desired would be if one had a platform where the system linker sometimes puts a variable at actual address zero (which arguably would be WTF, but imagine that we're stuck with the ABI). Because the address of a defined object must not be null, the C compiler would have to use another bit pattern for null pointers, for example by xoring with 0xFFFF at each cast between pointer and integer types.
Admin
In JavaScript confirm() will always display "OK" / "Cancel" buttons and return TRUE or FALSE. If I got the last part of the Custom_Confirm function described earlier right it works as a reverse confirm (returns true on Cancel and false on OK). The sad fact is you can always use ! to check for the opposite response, writing a function for this is... utterly stupid in real world systems).
Admin
Thinking a little bit more on the issue it seems to be a flaw in the User Interface thinking... confirm() should be used only to CONFIRM an action taken by the user, clicking Cancel should do exactly that (return false the the default action and therefor canceling it action).
A simple use of this would be to confirm a link being clicked while a form has been edited but not saved ("You have unsaved changes, Dismiss and continue?")
Admin
Wake me up when you find the premise. If ever.
Admin