Microsoft KB Archive/68320

DLL Remains in Memory After Calling Application Terminates ID Number: Q68320

3.00 WINDOWS

Summary:

Every time a Windows application loads a DLL, the module usage count for that DLL is incremented by 1. As long as the module usage count is greater than zero, the DLL will remain in memory. Windows decrements this count when FreeLibrary is called, and determines whether the library should be discarded.

If a DLL remains in memory after all the calling applications terminate, the system will experience problems when one of the calling applications is loaded for a second time.

More Information:

When a DLL remains in memory after its calling applications have terminated, it is likely that one of the following situations has occurred:


 * 1) The library name in the module definition (DEF) file contains lowercase letters.
 * 2) FreeLibrary is not called.
 * 3) FreeLibrary is called from a windows exit procedure (WEP).

If the problem is caused by the first situation, convert the name of the library in the module definition file to uppercase letters. Because of an interaction problem between LINK 5.10 and Windows 3.00, Windows will increment the lock count of the DLL twice, rather than once, when the library is loaded into memory. Thus, when FreeLibrary is called to decrement the lock count of the DLL, the lock count is not decremented to zero. For more information on this interaction, query on the following words:

prod(winsdk) and DLL and unload

If the library name in the module definition file is in uppercase letters, you will have to investigate the situation further. One approach is to conditionally compile some debugging code into the application so that you can monitor the DLL usage count when the application calls LoadLibrary and FreeLibrary, and at the application’s entry and exit points. The debugging code may resemble the following:


 * 1) define MODULEUSAGE // Use this to compile the debugging code


 * 1) ifdef MODULEUSAGE char szModUsageBuf[80]; // Debug output buffer #endif


 * 1) ifdef MODULEUSAGE // Use this to monitor the reference count wsprintf((LPSTR)szModUsageBuf, (LPSTR)“Usage Count:%u %s”, GetModuleUsage(GetModuleHandle((LPSTR))), (LPSTR)); OutputDebugString((LPSTR)szModUsageBuf); #endif

The first piece of the above code defines the MODULEUSAGE variable so that the debugging blocks of code will compile. The second piece defines an output buffer for temporary use. The third piece of code displays the usage count of the DLL on the debugging monitor. The monitoring code should be placed into the application in the following three points:


 * 1) At the start of the application, if the DLL is implicitly loaded
 * 2) Immediately after each LoadLibrary call, if the DLL is explicitly loaded
 * 3) Immediately before the application terminates

The information provided by this debug code will provide evidence that the usage count is or is not growing and shrinking by 1 (one) with each call to LoadLibrary and FreeLibrary.

A third situation that can cause a DLL to remain in memory after all calling applications terminate occurs if the WEP in the DLL is used to free the library. The WEP is designed to be the standard place where a DLL can perform any required tasks before the DLL is removed from memory. Unfortunately, in Windows 3.00, this standard is not fully implemented and the WEP may or may not be called. For more information on the WEP function, query on the following words:

prod(winsdk) and WEP

If the design of a DLL requires the WEP in the DLL to free another DLL, the second library will not be freed if the first library’s WEP is not called. To remedy this situation, remove the FreeLibrary call from the WEP and place it into a termination routine. Any application using the library can explicitly call the termination routine to ensure that the correct FreeLibrary call is made.