It has been common since the 1970s for programming languages to support heap-allocated memory. By using dynamic data structures, programmers can not only avoid the all too common pitfalls of fixed-size data structures, but they can also use complex data structures to construct efficient algorithms or to model real world problems more closely. However, heap allocation presents problems both for the programming language user and for the implementer. For the former, heap allocation is difficult to manage correctly; for the latter, it is hard to implement efficiently.
Programmers very soon discover the perils of managing
heap-allocated memory by hand (i.e. with malloc/free in C or
new/delete in C++). It is all too easy to deallocate memory either
too soon, leaving dangling pointers down which their program may
eventually stumble, or too late, leading to space leaks as the memory
residency of their program grows without bound. Unfortunately, and for
very good reason, memory management errors are not confined to
novices: at least one study has shown that up to 40% of programmer
time is wasted on hunting down memory management errors.
In order to free an object safely, programmers must be sure that it can no longer be accessed by their program. But this is not a local decision: liveness is a global property and here explicit memory management cuts against good software engineering principles of abstraction and modularity. A programmer should be able to understand the behaviour of a module from, in the worst case, a few neighbouring modules. But explicit allocation can allow one module to cause the failure of another through space leaks or premature reclamation of storage: the behaviour of the module is no longer independent of the context in which it is used. Adding memory management book-keeping detail to module interfaces weakens abstractions and reduces extensibility. Since liveness is a non-local matter, changes to book-keeping code may radiate beyond the module being developed. If objects are to be reused in different contexts, the new context must understand these rules of engagement, but this reduces the freedom of composition of objects. Although a wide range of tools are available to check correct usage of heap memory (for example, Purify, Bounds Checker, Great Circle and others), they are only practically useful as debugging aids since they impose a considerable run-time overhead on programs (and are typically not used when the software is deployed). Although these tools are often very useful for tracking down programming errors, considerable effort still must be devoted to correcting them. Debugging tools tackle the symptoms rather than the disease itself.
Object-oriented programming was the dominant paradigm of the 1990s. The advantages of object-orientation for both design and implementation are well known. One feature shared by all modern object-oriented languages is automatic dynamic memory management (or `garbage collection'): the programmer is relieved of the burden of deciding when an object can no longer be used and thus when it is safe to free the memory it occupies. Garbage collection provides a solution by uncoupling the problem of memory management from class interfaces instead of dispersing it throughout the code. Garbage collection research has recently enjoyed a rapid growth of interest due to the continually increasing popularity of programming languages that support or require automated memory management, most notably Java. Two reasons for Java's success are the increased productivity, leading to more rapid development times, afforded to the programmer by garbage collection and the decreased number of memory-management-related faults in deployed systems. However, Java is no exception: nearly all modern programming languages (such as C#, Eiffel, Haskell, Modula-3, Perl, Python) provide automatic memory management in one form or other, and even older languages like C/C++ permit it (garbage collector libraries for C/C++ are widely available ). Garbage collection is also essential in distributed systems where programmers have even less control over the behaviour of interacting components. It is clear that, whatever the dominant programming paradigm of the early 21st century may be, it will require automatic dynamic memory management.
Problems with this page?
Contact the mm-net webmaster
Last modified Tue Jan 8 17:45:40 GMT 2002