PRB: DLLs Not Unloaded After Calling CoFreeUnusedLibraries (301357)



The information in this article applies to:

  • Microsoft COM, when used with:
    • the operating system: Microsoft Windows 95
    • the operating system: Microsoft Windows 98
    • the operating system: Microsoft Windows Millennium Edition
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows NT 4.0

This article was previously published under Q301357

SYMPTOMS

Dynamic-link libraries (DLLs) that are not in use may not be unloaded from the process space after calling the CoFreeUnusedLibraries function.

CAUSE

This problem occurs when the application still has references to the components in the DLL, or when the application releases all the references to a DLL but does not make a subsequent call to CoFreeUnusedLibraries.

RESOLUTION

CoFreeUnusedLibraries does not immediately release DLLs that have no active object. There is a ten minute delay for multithreaded apartments (MTAs) and neutral apartments (NAs). For single-threaded apartments (STAs), there is no delay. The ten minute delay for CoFreeUnusedLibraries is to avoid multithread race conditions caused by unloading a component DLL.

To work around the problem, make a second call to CoFreeUnusedLibraries after ten minutes, or make periodic calls to CoFreeUnusedLibraries. For applications that run for long periods, such as Windows NT Service applications, calling CoFreeUnusedLibraries periodically ensures that DLLs that are not being used are unloaded.

Another workaround is to call CoUninitialize, which closes the COM library and releases all resources used by the current thread.

STATUS

This behavior is by design.

MORE INFORMATION

Steps to Reproduce Behavior

The following example uses the Microsoft XML Parser version 3 to demonstrate this behavior. This parser can be downloaded and installed from the following Microsoft Developer Network (MSDN) Web site:
  1. Create an empty Win32 Console Application in Microsoft Visual C++ 6.0.
  2. Save the following code as main.cpp and add it to the project:
    #include <stdio.h>
    #include <conio.h>
    
    #import "msxml3.dll" named_guids raw_interfaces_only
    using namespace MSXML2;
    
    // Global instance to force load/unload of OLE.
    struct InitOle {
        InitOle()  { ::CoInitialize(NULL); }
        ~InitOle() { ::CoUninitialize();   }
    } _init_InitOle_;			
    
    // Function declarations.
    inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
    
    void main()
    {
    
    	try
    	{
    		printf( "Note that the msxml3.dll is not loaded yet. Press any key to start the test.\n\n" );
    		_getch();
    
    		// Create an instance of DOMDocument.  This will load Msxml3.dll into the process.
    		IXMLDOMDocument *pDoc = NULL;
    		HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
    			IID_IXMLDOMDocument, (LPVOID*)&pDoc);
    
    		TESTHR(hr);
    
    		// Release the reference.
    		if (pDoc) pDoc->Release();
    		
    		// Free unused resources.
    		CoFreeUnusedLibraries();
    		
    		printf( "Now the DLL is loaded into the process. Monitor the process and note that the DLL will not be released even after 10 minutes. Then press any key to continue..\n\n" );
    		_getch();
    
    		// Second call.
    		CoFreeUnusedLibraries();
    		
    		printf( "Now the DLL should have been unloaded. Press any key to finish.\n\n" );
    		_getch();
    
    	}
    	catch(_com_error &e)
    	{
    		printf("Com Error:\n");
    		printf("Code = %08lx\n", e.Error());
    		printf("Code meaning = %s\n", (char*) e.ErrorMessage());
    		printf("Source = %s\n", (char*) e.Source());
    		printf("Error Description = %s\n", (char*) e.Description());
    	}
    }
    					
  3. Run the application and use a utility, such as Process Explorer from Sysinternals (see "References"), to monitor the loading and unloading of Msxml3.dll.

REFERENCES

Process Explorer is available from the following Web site:
The third-party products that are discussed in this article are manufactured by companies that are independent of Microsoft. Microsoft makes no warranty, implied or otherwise, regarding the performance or reliability of these products.

Microsoft provides third-party contact information to help you find technical support. This contact information may change without notice. Microsoft does not guarantee the accuracy of this third-party contact information.

Modification Type:MinorLast Reviewed:11/22/2005
Keywords:kbprb KB301357