tags:

views:

445

answers:

9

This seems like a lot of work; to check for null each time an object is used.

I have been advised that it is a good idea to check for null pointers so you don't have to spend time looking for where segmentation faults occur.

Just wondering what the community here thinks?

A: 

I think that is a good idea for a debug version.
In a release version, checking for null pointers can result in a performance degradation.
Moreover, there are cases where you can check the pointer value in a parent function and avoid the checking in its children.

Maurizio Reginelli
Gee, dude, imagine the performance degradation that would be caused by a null pointer dereference explosion and resulting system crash. I think it was Tony Hoare who something along the lines of running with checks enabled during debug, and turning them off for production, was like wearing your life jacket in the harbor, and taking it off once you got out onto the open ocean. The technical term for this behavior is "not smart".
John R. Strohm
@John: Then you think that adding a check every time a pointer is used in a routine that must be executed in a fast way is better? I'm considering C++ a language to use in situations where the performance is the first target.
Maurizio Reginelli
Tony Hoare's comments apply to checking stuff like memory allocation failures (NULL for malloc, std::bad_alloc for new). The kind of NULL checks mentioned here is more akin to checking for leaks in your boat. Useful in the harbor, but once on the ocean you'll only look after you hit something.
MSalters
+1  A: 

the answer is yes, if you are not in control of the object. that is, if the object is returned from some method you do not control, or if in your own code you expect (or it is possible) that an object can be null.

it also depends on where the code will run. if you are writing professional code that customers / users will see, it's generally bad for them to see null pointer problems. it's better if you can detect it beforehand and print out some debugging information or otherwise report it to them in a "nicer" way.

if it's just code you are using informally, you will probably be able to understand the source of the null pointer without any additional information.

Jeff
"it's generally bad for them to see null pointer problems": +1 for understatement! I'd actually go a step further: it is UNACCEPTABLE for a customer to see a null pointer problem.
John R. Strohm
It's equally unacceptable to see a `std::bad_alloc` or a `MyApp::NullPointerException`. Checking for NULL isn't sufficient, you need to solve the problem. Likely you can't solve it at runtime, because you've ran into a bug of unknown magnitude. Furthermore, a null pointer crash will be reported through Windows Error Reporting. A "controlled" failure likely will not.
MSalters
+2  A: 

I hate the amount of code checking for nulls adds, so I only do it for functions I export to another person.

If use the function internally, and I know how I use it, I don't check for nulls since it would get the code too messy.

brickner
+16  A: 

Use references whenever you can, because they can't be null, therefore you don't have to check if they are null.

It's good practice to check for null in function parameters and other places you may be dealing with pointers someone else is passing you. However, in your own code, you might have pointers you know will always be pointing to a valid object, so a null check is probably overkill... just use your common sense.

I don't know if it really helps with debugging because any debugger will be showing you pretty clearly that a null pointer was used and it won't take long to find it. It's more about making sure you don't crash if another programmer passes in NULL, or that the mistake is picked up by an assert in a debug build.

AshleysBrain
This seems reasonable :) thanks!
jm1234567890
References are syntactic sugar for pointers, no more, no less. Most certainly there is nothing that prevents null references. Forming a null reference violates the language specification and invokes undefined behavior, but passing a null pointer to a function whose contract forbids it is equally illegal. And realistically, both have the same result -- typically an access violation where the pointer or reference is used, not in the code violating the contract. *Because they can't be null* is the single most misguided reason for using references yet also the most commonly cited.
Ben Voigt
References can't be null *with defined behavior*. Pointers can. Rvalues can bind to const references so they are guaranteed to always refer to a valid objects, but you can't do that with const pointers. Creating a NULL pointer is just a matter of assigning NULL, but with references requires either unusual syntax or writing code that dereferences a pointer. I don't think it's fair to compare them as equals. Within the rules of the language, references can't be null, and pointers can.
AshleysBrain
Kernighan and Plauger, in their book "Software Tools", advocated doing the error checks anyway, and printing "can't happen" when an error that can't possibly happen has occurred anyway. They report finding themselves very rapidly humbled by the number of times they saw that message pop out on their terminals. Even if you KNOW the pointer can't be NULL, "trust, but verify." Also note: if a pointer that you know can't be NULL pops up NULL anyway, it is symptomatic of a bug somewhere else, and you probably want to find and fix that bug.
John R. Strohm
jalf
+11  A: 

No. You should instead make sure the pointers were not set to NULL in the first place. Note that in Standard C++:

int * p = new int;

then p can never be NULL because new will throw an exception if the allocation fails.

If you are writing functions that can take a pointer as a parameter, you should treat them like this

// does something with p
// note that p cannot be NULL
void f( int * p );

In other words you should document the requirements of the function. You can also use assert() to check if someone has ignored your documentation (if they have, it's their problem, not yours), but I must admit I have gone off this as time has gone on - simply say what the function requires, and leave the responsibility with the caller.

A third bit of advice is simply not to use pointers - most C++ code that I've seen overuses pointers to a ridiculous extent - you should use values and references wherever possible.

anon
You would be amazed at how many people think new returns NULL on failure. (By looking at other people's code.) This is probably a carry-over from C.
George Edison
Well, the assert says the same as the comment, and also enforces it, unless disabled.
UncleBens
@George: it was true of C++ at one time as well (before exception handling was added). If that's what you want, you can get it with `x = new(nothrow) whatever;`
Jerry Coffin
@George I've spent over 10 years as a teacher, instructor and consultant - _nothing_ can amaze me any more.
anon
@Uncle Yes, but it seems like belt and braces - if I had to choose one, I'd rather have the documentation. And I don't like the idea someone could be depending on the assert to detect a bug, which after all is not in MY code.
anon
@George: "You would be amazed at how many people think new returns NULL on failure" - You would be amazed how far behind the "standard" the standard libraries shipped for embedded devices are...
Johann Gerell
+4  A: 

In general, I would advise against doing this, as it makes your code harder to read and you also have to come up with some sensible way of dealing with the situation if a pointer is actually NULL.

In my C++ projects, I only check if a pointer (if I am using pointers at all) is NULL, only if it could be a valid state of the pointer. Checking for NULL if the pointer should never actually be NULL is a bit pointless, because you are then trying work around some programming error you should fix instead.

Additionally, when you feel the need to check if a pointer is NULL, you probably should define more clearly who owns pointer/object.

Also, you never have to check if new returns NULL, because it never will return NULL. It will throw an exception if it could not create an object.

Simon Lehmann
@Simon: I'm in an older C++ environment on an embedded platform. Of course `new` can return NULL!
Johann Gerell
A: 

If the pointers are coming to you as parameters to a function, then make sure they are valid at the beginning of the function. Otherwise, there is not much point. new throws an exception on failure.

George Edison
In general, it's not possible to check if a pointer is "valid".
anon
@Niel: By valid, I mean not-NULL.
George Edison
+1  A: 

I figure I can do a whole lot of checks for NULL pointers for the cost of (debugging) just one segfault.

And the performance hit is negligible. TWO INSTRUCTIONS. Test for register == zero, branch if test succeeds. Depending on the machine, maybe only ONE instruction, if the register load sets the condition codes (and some do).

John R. Strohm
+1  A: 

Others (AshleysBrain and Neil Butterworth), already answered correctly, but I will summarize it here:

  1. Use references as much as possible
  2. If using pointers, initialize them either to NULL or to a valid memory address/object
  3. If using pointers, always verify if they are NULL before using them
  4. Use references (again)... This is C++, not C.

Still, there is one corner case where a reference can be invalid/NULL :

void foo(T & t)
{
   t.blah() ;
}

void bar()
{
   T * t = NULL ;
   foo(*t) ;
}

The compiler will probably compile this, and then, at execution, the code will crash at the t.blah() line (if T::blah() uses this one way or another).

Still, this is cheating/sabotage : The writer of the bar() function dereferenced t without verifying t was NOT null. So, even if the crash happens in foo(), the error is in the code of bar(), and the writer of bar() is responsible.

So, yes, use references as much as possible, know this corner case, and don't bother to protect against sabotaged references...

And if you really need to use a pointer in C++, unless you are 100% sure the pointer is not NULL (some functions guarantee that kind of thing), then always test the pointer.

paercebal