home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


CHAPTER 13
MEMORY MANAGEMENT TECHNIQUES USING CLASSES

How do I...

  13.1 Make a simple class to clean up dynamically allocated memory automatically?
  13.2 Make a class that automatically cleans up objects allocated with new?
  13.3 Make an object that deallocates itself when there is no more code referencing it?

Managing memory is something few programmers think about when designing a program, but wish they had when staring at debugger output. Although performance tuning of a program will often deal with memory management issues, memory management is more than just counting the bytes allocated and deallocated in a program.

Shuffling bytes around in main memory is one of the slowest operations on a computer, and although it’s faster than accessing the hard disk or the video memory, things would go much faster if the only thing the processor had to fetch from main memory was code. Your operating system does a lot of shuffling of data in memory in its management of caches and other data areas, as well as handling things like virtual memory (which allows your computer to use free disk space as an extension to system RAM). This is a relatively fixed cost, but as a programmer you have control over how your program uses memory (how much, how often things are copied, and so on).

Another technique no programmer should be without is a basic understanding of how memory managers are implemented and their limitations. Easy-to-implement techniques are also covered because for most programs these produce excellent results with minimal effort.

13.1 Make a Simple Class to Clean Up Dynamically Allocated Memory Automatically

This How-To uses scope to automatically deallocate dynamically allocated memory. It is most useful in situations in which the new and delete operators aren’t the most efficient. This allows experimentation with other allocation schemes, such as operating system API calls, to be done invisibly to the rest of the program.

13.2 Make a Class That Automatically Cleans Up Objects Allocated with new

This How-To uses a template for type-safe memory management to provide functionality similar to that of How-To 13.1, it underlines a different approach.

13.3 Make an Object That Deallocates Itself When There Is No More Code Referencing It

Counting the number of references to an object is useful in multithreaded programming environments because objects might not have finished being processed by other threads when the thread that allocated the object expires.

13.1 Make a simple class to clean up dynamically allocated memory automatically?

Problem

You might want to do this for a number of reasons. The primary reason is so the user of the class does not need to remember to match up new calls with deletes because the scope mechanism and the class destructor will handle it automatically. This is not the only reason, though.

Some systems (Windows 3.1, most notably) do not lend themselves well to the use of new and delete operators (which, for the most part, eventually call malloc() or free()). Often this problem comes from the memory manager or the system’s segmentation model. Under the 16-bit Windows operating systems, most data allocated using new and malloc() comes from the application’s local heap, which is only 64KB in size. Although more memory can be had using global memory allocation functions, managing it is quite a hassle.

Operating system direct memory allocation functions are often quite complicated, with lots of arguments and so on. The use of these functions also makes porting the code difficult. Another reason might be that the operating system provides a more robust heap manager (OS/2 provides an extremely fast memory suballocation manager, for instance).

Encapsulating the process in a memory manager helps the process in a number of ways:

  It keeps the actual function calls to the operating system’s memory allocation routines in one place. This makes porting the code easier because the memory allocations in the program need not change as long as the memory allocation object’s interface remains the same.
  It’s possible to experiment with different memory allocation techniques (which are not necessarily operating system–specific) without affecting the code that uses the memory management class.
  It is easy to keep statistics on the memory the program used.
  The memory-managing object can perform all the error checking, and even handle the problems in a way best suited to the operating system without the users’ (that is, the other programmers) of the object knowing how it’s done.
  A memory object can perform advanced functions such as reference counting, providing a copy-on-write scheme, and also calling operating system–optimized resizing functions to increase program performance and reliability.
  The memory object can automatically deallocate the memory after the object falls out of scope. This can reduce the occurrence of memory leaks tremendously. Just think of what could happen to an application if a delete call were missed in a function called one million times!

These techniques require some discipline to implement. It is sometimes difficult to unlearn the use of new and delete for one project, but these techniques can go a long way toward reducing the amount of debugging time for a project.

Steps

It is best to start out with code that is generic enough to be used everywhere in the program. After that, it’s possible to use this code in overloaded new and delete operators, for example. In this example, the code will be modularized as well as object-oriented. It essentially entails keeping the code specific to memory management in one C++ file, which is compiled with the other code. Programmers get the definitions for the classes through a header file. Because this code is quite generic, placing it in a module makes it easier to reuse elsewhere.

This example will use only the new and delete functions because they are available in every C++ system to allow memory to be allocated dynamically that automatically deallocates itself when the object managing it falls out of scope. In this case, it will also be possible to implement operators to work on the memory if this functionality is desired, or, for instance, to set the memory contents to 0 before making it available for use.

There are as many approaches to this problem as there are C++ programmers. The example detailed here will allocate generic memory.

This code is best put into a header file to make it more reusable.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.