DOCUMENT:Q187684 19-JUL-2001 [visualc] TITLE :BUG: Assert When Calling AfxFreeLibrary from ExitInstance PRODUCT :Microsoft C Compiler PROD/VER:winnt:2.0,2.1,2.2,4.0,4.1,4.2,5.0 OPER/SYS: KEYWORDS:kbDLL kbMFC kbVC200bug kbVC400bug kbVC500bug kbOSWin95 kbDSupport kbGrpDSMFCATL ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - Microsoft Visual C++, versions 2.0, 2.1, 2.2, 4.0, 4.1, 4.2, 5.0, on platform(s): - the operating system: Microsoft Windows 95 ------------------------------------------------------------------------------- SYMPTOMS ======== The following assertion in Afxcrit.cpp line 73 can fail when you call the AfxFreeLibrary function from the ExitInstance function of an MFC DLL: ASSERT(!_afxResourceLocked[i]); Similarly, an access violation or an unhandled exception may occur when you call FreeLibrary from ExitInstance or the DllMain function during DLL_PROCESS_DETACH. CAUSE ===== The Windows 95 loader is not reentrant. Causing a DLL to be freed while in the process of freeing another DLL can cause a dependent DLL to be freed unexpectedly. For example, if a DLL (A) with a dependant DLL (B) and a reference count of 0 calls FreeLibrary from DLL_PROCESS_DETACH on another DLL (C), the Windows 95 unloader rescans the dependent DLL list and prematurely releases the dependent DLL (B). The DLL (A) that calls FreeLibrary is protected because it is marked. Upon returning from FreeLibrary, DLL (A) might make further calls into DLL (B) and cause the assertion or access violation. RESOLUTION ========== Don't call AfxFreeLibrary from ExitInstance. Likewise, don't call FreeLibrary from either ExitInstance or from DLL_PROCESS_DETACH of the DllMain function. You can work around this bug by providing initialization and uninitialization functions that are not called from within DllMain. For example, if you use an ActiveX DLL, you can call AfxLoadLibrary and AfxFreeLibrary from the COM object's constructor and OnFinalRelease function. Calling AfxFreeLibrary from a destructor of a static object does not work because the static object constructors and destructors are called from DllMain. An alternative workaround is to increment the reference count of the DLL with a 0 reference by calling (Afx)LoadLibrary again. STATUS ====== Microsoft has confirmed this to be a bug in Windows 95. We are researching this bug and will post new information here in the Microsoft Knowledge Base as it becomes available. MORE INFORMATION ================ In MFC, DLLs are dynamically loaded and unloaded using AfxLoadLibrary and AfxFreeLibrary, respectively. A common mistake when using AfxFreeLibrary (or FreeLibrary) is to call it from ExitInstance of an MFC DLL. A similar problem occurs when you call FreeLibrary from DllMain with DLL_PROCESS_DETACH. When you call FreeLibrary from DllMain during DLL_PROCESS_DETACH under Windows 95, the entire dependency tree is reevaluated. If any DLL other than the one currently calling FreeLibrary has a reference count of 0, it will be unloaded. In some cases, this can cause problems if there are still calls to the unloaded DLL. A common example is when the CRT libraries are prematurely unloaded. To work around this problem, you can make an additional call to LoadLibrary for the CRT libraries before you call FreeLibrary. Additional query words: ====================================================================== Keywords : kbDLL kbMFC kbVC200bug kbVC400bug kbVC500bug kbOSWin95 kbDSupport kbGrpDSMFCATL Technology : kbVCsearch kbAudDeveloper Version : winnt:2.0,2.1,2.2,4.0,4.1,4.2,5.0 Issue type : kbbug Solution Type : kbpending ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.