Interpreting an Object Dump

The preceding dump comes from the memory checkpoint example introduced in Detecting a Memory Leak in the topic Detecting Memory Leaks. Remember that there were only two explicit allocations in that program — one on the frame and one on the heap:

// do your memory allocations and deallocations ...
CString s = "This is a frame variable";
// the next object is a heap object
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );

Start with the CPerson object; its constructor takes three arguments that are pointers to char. The constructor uses these arguments to initialize CString member variables for the CPerson class. In the memory dump, you can see the CPerson object listed along with three nonobject blocks (3, 4, and 5) that hold the characters for the CString member variables. These memory blocks will be deleted when the destructor for the CPerson object is invoked.

Block number 2 represents the CPerson object itself. After the CPerson address listing, the contents of the object are displayed. This is a result of DumpAllObjectsSince calling the Dump member function for the CPerson object.

You can guess that block number 1 is associated with the CString frame variable because of its sequence number and its size, which match the number of characters in the frame CString variable. The allocations associated with frame variables are automatically deallocated when the frame variable goes out of scope.

In general, you shouldn’t worry about heap objects associated with frame variables because they are automatically deallocated when the frame variables go out of scope. In fact, to avoid clutter in your memory diagnostic dumps, you should position your calls to Checkpoint so that they are outside the scope of frame variables. For example, place scope brackets around the previous allocation code, as shown here:

oldMemState.Checkpoint();
{
    // do your memory allocations and deallocations ...
    CString s = "This is a frame variable";
    // the next object is a heap object
    CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
}
newMemState.Checkpoint();

With the scope brackets in place, the memory dump for this example is as follows:

Dumping objects ->

{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4

Last Name: Smith
First Name: Alan
Phone #: 581-0215

Notice that some allocations are objects (such as CPerson) and some are nonobject allocations. “Nonobject allocations” are allocations for objects not derived from CObject or allocations of primitive C types such as char, int, or long. If the CObject-derived class allocates additional space, such as for internal buffers, those objects will show both object and nonobject allocations.

Notice that the memory block associated with the CString frame variable has been deallocated automatically and does not show up as a memory leak. The automatic deallocation associated with scoping rules takes care of most memory leaks associated with frame variables.

For objects allocated on the heap, however, you must explicitly delete the object to prevent a memory leak. To clean up the last memory leak in the previous example, you can delete the CPerson object allocated on the heap, as follows:

{
    // do your memory allocations and deallocations ...
    CString s = "This is a frame variable";
    // the next object is a heap object
    CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
    delete p;
}

For more information, see Detecting a Memory Leak and _CrtMemDumpAllObjectsSince.