The Art of Leaking
By kto on May 09, 2005
The Art of Leaking
by Dr. Lee Kerman
Historically, the art of creating memory leaks in native code was
simple. There were many simple techniques you could use:
- Use lots of strdup() calls, most programmers forget that strdup() actually returns malloc() space so they won't notice that the appropriate free() call is missing.
- Make sure there is lots of control flow statements where the free() calls are, that way you can have a few paths through the code that will miss a free() call or two.
- Early allocations during initialization aren't big leakers, but you can always hide a few leaks during initialization, they won't notice and it's often hard to know when to free up memory that was allocated at initialization.
- Use lots of malloc() and lots of free() calls for the same basic object, don't make it easy to match up the allocation with the freeing, you can always confuse the code enough so that a few missed free() calls won't be noticed. But be careful that free() isn't called with a NULL or garbage pointer, that may cause the application to crash and they might find your leak. Unless you also want to create strange crashes in addition to memory leaks, creating crashes will be the topic of another paper by C.R. Ashem.
- Add comments like "/\* Don't free this space \*/" with no further details just before a malloc() call, it will usually keep the less curious away for awhile, but you can't do this very often or your'll give it away. In general, old stale comments often prevent people from changing the code around it out of fear that they will create a regression. Nevermind that the root of the problem had been fixed 5 or 10 years ago and the comments could be deleted, few people will delete comments that look important but don't provide enough information as to why it was important.
With the advent of Java, the art of memory leaking has gone into a new era. You can't just leak memory like the old days, you really need to work at it, creating convoluted data structures and effectively keeping a reference to objects that aren't really needed, but appear to be.
So the techniques used to create Java leaks are a bit more complicated:
- Save everything. If your application has an "Undo" feature, allow for an infinite undo list. If it opens files, always save a reference to the old files. The field "previous" is ideal for this, always save the "previous" objects.
- Create your own caches for objects, this really messes up the garbage collection and makes it look like your code is trying to be efficient, so it's easy to hide the fact that you have cached lots of memory objects.
- Use finalizers to free up objects and open files and sockets. Often the finalizers never run and they won't figure this one out easily because some finalizers will be run but some won't.
- Never null out any field references, they won't notice that it wasn't null'd out and that will keep the object alive even after you don't need it anymore.
- Allocate your arrays much larger than necessary, although not a leak, if all arrays are twice as big as needed, it might as well be a leak. Why bother figuring out what size you really need?
- Allocate some extra class loaders and make sure they load a few classes, then hang onto the objects created from those classes. This creates a huge chain of objects that will never get garbage collected.
So as you can see, you can still create leaks in Java, it's just a bit more
convoluted that it used to me.
Dr. Lee Kerman is a professional leaker and has determined that memory leaks provide job security for all programmers.