Microsoft KB Archive/264295

From BetaArchive Wiki

Article ID: 264295

Article Last Modified on 4/11/2003



APPLIES TO

  • Microsoft Windows DNA



This article was previously published under Q264295

SUMMARY

This article describes two common C++ programming mistakes that can cause memory leaks in your application.

MORE INFORMATION

Mistake #1: Not Freeing Memory Allocated by SafeArrayGetElement() When Using Variants

When you use SafeArrayGetElement(), be sure to free the memory that has been allocated for the copy of the safe array element.

It is the caller's job to allocate memory for this function to copy the safearray data element into, and therefore it is also the caller's job to release this memory when finished with it. SafeArrayGetElement() will allocate the memory for the data in the Variant (such as for a BSTR), and it is the caller's job to free all memory that is associated with the variant. The best approach for doing this is to use the VariantClear() function. Here is an example:

...
   VARIANT varMyVal;  // Variant allocated on stack
   HRESULT hResult;
   long ix;

   VariantInit(&varMyVal);

   ix = 1;

   // If the element in the safe array fetched was a BSTR, then the
   // appropriate memory will be allocated for it, on the heap
   hResult = SafeArrayGetElement(m_psa, &ix, &varMyVal);

   // This will free the memory for the data element retrieved from
   // the Safe Array (say a BSTR)
   VariantClear(&varMyVal); 
...
                



Mistake #2: Not Calling Release on COM Interface Pointers When Using QueryInterface()

When you are using in-process COM components, make sure that you release all interface pointers. If you do not do this, you may leave instances of unused COM components allocated in the process's memory space.

The following code shows the proper handling of a pointer, pObj, obtained via QueryInterface() on an existing object pointed to by pUnk. The pObj->Release(); will decrement the reference count on the object, but the object won't be released from memory at that point because pUnk is still holding a reference to it. When pUnk->Release(); is called, the ref count will go to 0 and the object will be released. If you omit the pObj->Release(); then the pUnk->Release(); will not free the object and you will have a memory leak in your process.

...
CMyAtlObj* pObj;
    
   if (!SUCCEEDED(pUnk->QueryInterface(CLSID_MyAtlObj, (void **)&pObj)))
        return NULL;
   //Use pObj

...

   pObj->Release(); // Needed because we called QueryInterface.
...
                

For COM components that are registered to run under Microsoft Transaction Server, there will be an entry written to the Windows NT Application Event Log by Microsoft Transaction Server when it detects that a hosted component has not been properly released before shutting down. The entry in the event log will have an Event ID of 4098 and a description of "Unexpected Object Reference Count". If you have these entries in the NT Application Event Log and you are experiencing memory leaks in those MTS packages (processes), then it is likely that COM interface pointers are not being released properly.

REFERENCES

For additional information, click the following article number to view the article in the Microsoft Knowledge Base:

253706 HOWTO: Isolate and Identify the Source of Inetinfo or Other Process Memory Leaks


Keywords: kbinfo KB264295