PRB: Memory Leak In COM When Repeatedly Creating STA Threads (289640)



The information in this article applies to:

  • Microsoft COM+ 1.0
  • Microsoft COM+ 1.5

This article was previously published under Q289640

SYMPTOMS

If you perform the following steps in a COM application repeatedly, a memory leak occurs:
  1. Create a new worker thread.
  2. Inside the worker thread, call CoInitialize(NULL) to initialize COM for single-threaded apartment (STA) concurrency model.
  3. After calling CoInitialize(NULL), create a new COM object using CoCreateInstance or CoCreateInstanceEx.
  4. Marshal the COM object using CoMarshalInterface into an IStream object.
  5. Release the marshaled COM object and associated IStream object data.
  6. Call CoUninitialize() and let the thread exit.
The following steps can also trigger a memory leak:
  1. Create a new worker thread.
  2. Inside the worker thread, call CoInitialize(NULL) to initialize COM for single threaded apartment (STA) concurrency model.
  3. After calling CoInitialize(NULL), unmarshal a previously marshaled COM object.
  4. Release the unmarshaled COM object and associated data.
  5. Call CoUninitialize() and let the thread exit.

RESOLUTION

This memory buildup does not occur if you initialize COM on the thread using CoInitializeEx(NULL,COINIT_MULTITHREADED).

MORE INFORMATION

Note that this leak was discovered by using the SQLOLEDB OLEDB provider in an application that repeatedly created new threads to service incoming requests. If Visual Studio 6.0 is installed on the computer, the SQLOLEDB provider internally marshals a pointer to a Visual Studio Analyzer COM interface every time you connect and, therefore, performs the set of operations that must occur for this memory buildup issue to occur.

The leak is per thread invocation. You can minimize the leak by following the standard Win32 programming practice of re-using a small set of worker threads in a thread pool. By doing this, you can avoid repeated creation of single use threads.

This problem does not affect COM+ hosted applications, because COM+ does not repeatedly create and shut down threads. This problem only affects programs that create threads and do not re-use those threads. To avoid this leak, Microsoft recommends that you use thread pooling first and foremost. Microsoft also recommends that you use CoInitializeEx(NULL,COINIT_MULTITHREADED) at the beginning of the worker thread code before you use COM. If you debug memory leaks using UMDH logs, you see the following memory leak stack when this situation occurs:

000F3350 bytes in 0x384 allocations (@ 0x00000450 + 0x00000A10) by: BackTrace00355
        ntdll!RtlDebugAllocateHeap+000000FD
        ntdll!RtlAllocateHeapSlowly+0000005A
        ntdll!RtlAllocateHeap+00000808
        ole32!COleCache::COleCache+0000012B
        ole32!CCtxChnl::Release+00000018
        ole32!CSurrogateProcessActivator::Release+0000000A
        ole32!CCacheNode::Save+000002AC
        ole32!UtHMFToMFStm+00000042
        ole32!CPubStream::GetSize+00000013
				

Modification Type:MajorLast Reviewed:9/25/2002
Keywords:kbBug kbDSupport kbprb KB289640