| Kristian Nielsen ( @ 2008-09-07 10:50:00 |
| Entry tags: | adobeflash, gc, programming |
Garbage collection and memory leaks
So, with automatic Garbage Collection, memory leaks are a thing of the past, right?
Well, not quite, of course. Automatic Garbage Collection, like most other automated programming techniques, necessarily needs to approximate (ie. guess), and while the guesses of garbage collectors are generally very good, they cannot magically predict the future.
The classic way that a program fools the garbage collector is by maintaining a
global list of objects created. This is a common technique for memory
management in non-garbage-collected programming environments, where such lists
will be used to ensure eventual free() of all objects in some
longer-lived manager object.
Unfortunately, if such techniques carry over to garbage collected environment, the effect is to effectively disable the automatic Garbage Collection algorithm! Every object allocated will have an outstanding reference in the global list, causing garbage collection to consider all of it live data, which cannot be deallocated.
I got hit by this while working on an Adobe Flash application using Papervision 3D. It was leaking tons of memory (on the order of 20Mb for every user interaction!).
Turns out that this was a case of the above-mentioned problem. It turns out that
every Papervision 3D MaterialObject3D object registers itself in
the constructor with the MaterialManager singleton, which is
nothing but a global list of allocated material objects. The result is that
no material objects (which all inherit from the
MaterialObject3D class) will get deallocated ever, unless
explicitly done by the application (using
MaterialObject3D::destroy() for example). So much for automatic
Garbage Collection...
A simple Google search reveals that I am not the first one to be hit by this.
The problem here is a poor design in the Papervision 3D API in this respect, made even worse by the fact that the documentation does not seem to mention this aspect at all (at least I could not find it). A constructor that automagically registers the object in a global list is generally a really poor idea in garbage collected programming environments.
I am not sure why Papervision 3D does this. Maybe it could just be removed. Or
alternatively, a better approach would be for the API to make it explicit that
such global registration is taking place. For example by forcing the application to
explicitly call some MaterialObject3D::register(), documenting
the need for unregister/destroy, or by not providing a constructor at all, and
instead creating objects in some factory class, again making clear mention of
the need to unregister/destroy.