Where does this catalogue of errors leave us? Tired, perhaps, if we don't already have the habit of thinking about memory usage in the abstract. Studying these examples is a good time investment because they cover the entire range of ways in which memory pointers can be misused. Once you fully understand the problems, two tasks remain: to do the same for memory leaks (we'll take up that subject in the next article); and to prevent and remedy these errors.
When developers go on campaigns to correct memory errors, their first thought is usually to employ memory-management tools; that is, programs and libraries that fix problems. That's a good instinct. Even in comparison with other programming aids, memory-management tools are quite valuable; the next two installments in this series will show how straightforward it is to use them, and what clear benefits they provide.
That's not where the greatest returns are, though. Software development remains primitive, with very little serious science available on its practice. No one has yet undertaken the rigorous comparisons necessary to conclude unequivocally which is the best way to stamp out memory errors. From what I've seen, though, the clear winners are such low-tech approaches as disciplined documentation and code review.
Here's what I mean.
One of your habits as a C or C++ coder should be to document in source comments the memory semantics of each function you implement. Consider this example of such a header comment:
/******* * * get_customer_object * * ... * * The return value of get_customer_object() is located * in the heap. The client code that invokes this * function is responsible for releasing the corresponding * memory with free(). * *******/ Customer *get_customer_object(...
Care in this one practice, which costs so little, pays off more than any other single approach to memory problems I know. Write explicit comments, with enough detail to be understood clearly. Your own code will probably improve, and the use of your definitions by coworkers will show far fewer errors.
The second big winner in memory hygiene is code review. Review takes many forms, including bench checks, pair programming, inspections, and so on. They're all good, and I'm happy to promote method whichever best fits your situation. Review applies particularly well to memory problems, because memory is both difficult enough to be a source of frequent errors, and simple enough that humans can use reason to understand it completely. With practice, most good C programmers can develop enough of an eye to validate the memory usage of short code segments thoroughlyand they should.
In the next article, we'll start to look at programming tools that complement these solutions to memory problems, and apply them particularly to problems of memory leaks. Are there specific tools or problems that interest you? Write me at email@example.com, and I'll address your questions in follow-up articles.