13

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?

1
  • 2
    Only if you know how to handle it Commented May 9, 2010 at 19:56

9 Answers 9

19

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.

Sign up to request clarification or add additional context in comments.

4 Comments

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.
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.
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.
Even better than references are plain value objects. A string* can be null, and has to be checked. A string& can't be null without invoking undefined behavior (so if it happens, it is a symptom of a bug elsewhere), but a string can never be null, in any shape or form.
13

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.

6 Comments

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.
Well, the assert says the same as the comment, and also enforces it, unless disabled.
@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;
@George I've spent over 10 years as a teacher, instructor and consultant - nothing can amaze me any more.
@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.
|
4

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.

1 Comment

I'm in an older C++ environment on an embedded platform. Of course new can return NULL!
2

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.

Comments

1

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.

2 Comments

"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.
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.
1

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).

Comments

1

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.

Comments

0

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.

3 Comments

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: 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.
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.
0

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.

2 Comments

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.