COM Task Allocator Memory Debugging Tools
Because of their distributed nature, COM clients and servers must manage memory differently than client and servers with client code and the object code that share the same memory pool. Whenever clients and objects need to transfer blocks of memory back and forth, they need to use the task allocator—a COM-provided memory allocator. Any time large pieces of memory need to be communicated between clients and objects, developers need to use the task allocator, which includes memory allocated for BSTRs. The only way to debug memory leaks from the task allocator is to implement an interface named IMallocSpy.
Windows provides a hook for tracking memory allocated by the COM Task Allocator. Developers wishing to plug into the task allocator to watch the memory allocations as they occur implement an interface named IMallocSpy and hand this interface over to Windows via the CoRegisterMallocSpy() function.
IMallocSpy provides pre- and post-processing functions for each function within the standard IMalloc interface. For example, IMalloc includes a function named Alloc(). IMallocSpy includes a function named PreAlloc() and a function named PostAlloc(). If an implementation of IMallocSpy has been plugged into the task allocator, the task allocator calls IMallocSpy::PreAlloc() before allocating memory and IMallocSpy::PostAlloc() after the memory has been allocated. This lets developers watch memory blocks as they’re being managed.
OTL provides a class named OtlMallocSpyImpl that tracks memory activity occurring within the task allocator and indicates that activity through trace statements in the debug window.
Using the Task Allocator Debugger
Using OTL’s task allocator debugger is straightforward.
// in the .CPP file:
using namespace StingrayOTL;
#include "otlmallocspy.h"
OtlMallocSpyImpl otlMallocSpy; // creating one of these registers
// a malloc spy...
//… Code that exercises the task allocator
//… otlMallocSpy is a global variable, so it unattatches from the
//… task allocator.
COtlMallocSpyImpl registers the IMallocSpy implementation with the system. Declaring an instance of COtlMallocSpyImpl turns on the debugging process. Task allocations appear in the output debug window as they occur. In addition, the task allocator spy informs you of any unreleased memory within its destructor.