How to avoid NULL pointers
Most programming languages (though not all) have the concept of null pointers or references. The most common languages to use null pointers are C/C++ (Java has null references, which are similar). Null pointers cause big headaches to developers because accessing one of them causes crashes or nasty exceptions, which are always associated to a programming defect.
Despite the problems with null pointers, they have valid uses such as checking if an operation finished correctly, or marking a particular value as unknown.
Even though it is possible to find legitimate uses for null pointers, they are not strictly necessary and may lead to unnecessary bugs. Here are some suggestions that can be used to reduced the number of null pointers. Using such suggestions depends on the programming style one wants to use (for example, some people are not concerned with checking null values). However, it is good to know some alternatives to existing practices.
Avoid Variables That Have Dual Meaning
Most of the problems with null pointers arise from functions where the return value has dual meaning. For example, a function may read some data from a file and return a pointer to the data structure or null if there was a problem.
It is clear that the return value here has a dual purpose: it may store a pointer to data, or a null value that signals a problem.
It understandable that some functions are easier to express using this arrangement. However, it may make your program unsafe, especially if there is a possibility that the caller forgets to test the return value.
An alternative to this use of null pointers is to create a separate parameter that stores an error code when the problem happens. This way you don’t need to have a null pointer to represent errors, and you can even have a better description of the error that actually occurred.
Use a Separate Value to Represent Unknowns
Another alternative to null pointers is to use a non-null, unique value that can be employed to represent an unknown element of the domain. For example, if you have a data structure that represents employees, you could create a singe, concrete object that can be used to represent an unknown employee.
An advantage of using this approach is that whenever you see a null pointer of that type if must mean an error. As such, null pointers are not propagated throughout the program, unless a real defect exists in your program.
Another advantage of this approach is that you don’t need to check for null pointers when calling functions and methods of such type. Since you already known that the underlying type is always non-null, you can call functions and methods directly. For example, if you are using C++ or Java, you can use
myObject.myMethod();
without even checking if myObject is null. Similar approaches can also work for C and related languages.
Using this approach, testing if an object is of the unknown type is just as easy as testing for null. Since the unknown object is unique, you can just check if the address is the same, which is almost as quick as testing for null (it may be slightly slower because, in most processors, it is faster to check against zero than other values).
Conclusion
Null pointers have advantages and disadvantages. However, they are not the only way to check for errors and special circumstances in a program. Alternative methods may make your program easier to write and avoid a number of problems associated with null pointer access.
Further Reading
C++ Pointers and Dynamic Memory Management, by Michael C. Daconta, discusses several issues related to pointers in languages such as C and C++. However, it has several ideas that are equally applicable to programmers in Java and C# as well.
Memory as a Programming Concept in C and C++, by F. Frank, is another interesting view of memory and how to manage it in C and C++. Again, memory is such an important concept that it is valuable for programers using other languages.
Other Links
Page for Null Pointers in the C Faq, explains what a NULL pointer is and how it is represented in several architectures.
Class notes on null pointers give a brief introduction to how to use null pointers.
Post on avoid null references on Lambda Ultimate provides some information on how these problems are avoided in Eiffel.
A paper mentioned on the previous page, about how to implement safety mechanisms against null dereferencing in Eiffel.