See the first post in The Pragmatic Programmer 20th Anniversary Edition series for an introduction.
Although there are no guaranteed ways of ensuring that you always free resources, certain design techniques, when applied consistently, will help. In the text we discussed how establishing a semantic invariant for major data structures could direct memory deallocation decisions. Consider how Topic 23, Design by Contract, on page 104, could help refine this idea.
Design by Contract could be used to enforce the semantic invariants for a given data structure. The code used to create, operate on and destroy the data structure can utilise pre and post conditions to ensure that the design techniques for deallocating memory are used. The text suggests that for procedural languages such as C:
… write a module for each major structure that provides standard allocation and deallocation facilities for that structure.
In Chapter 3 of “Writing Solid Code”, author Steve Maguire takes this idea further; implementing memory allocation/deallocation bookkeeping in order to codify and enforce correct and safer resource management. Furthermore, throughout the book Maguire utilises design by contract through use of C’s
assert macro. Using design by contract and the concepts from Maguire’s book, I implemented a queue data structure module in C. The full implementation can be found on my GitHub: C Data Structure Memory Management Example.
This approach is certainly not perfect, it is certainly an improvement over uncontrolled usage of
Some C and C++ developers make a point of setting a pointer to
NULLafter they deallocate the memory it references. Why is this a good idea?
This is one method to help prevent use after free errors. In C/C++, there is no way of determining whether a pointer is valid - i.e. it could be pointing to unallocated memory. Using an invalid pointer can cause many issues, most notably corrupting valid data and potential execution of arbitrary code. Setting a pointer to
NULL will reliably generate runtime error if it is dereferenced - crashing the program instead of allowing use after free errors to go unnoticed.
Some Java developers make a point of setting an object variable to
NULLafter they have finished using the object. Why is this a good idea?
Java uses garbage collection to automatically manage deallocation of memory without the programmer explicitly doing so as in C. Part of this garbage collection is reference counting, whereby an object will be deallocated if there are no references to it in the current state of the program. Setting an object variable to
NULL decrements the reference count for that particular object so that it can be garbage collected. In long running applications, such as a web server, this can be important to prevent memory utilisation from constantly increasing over time due unused objects continuing to be referenced within the program.