Microsoft KB Archive/264295

= INFO: Two Common C++ Programming Mistakes Can Cause Memory Leaks =

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.



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 &quot;Unexpected Object Reference Count&quot;. 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. 