BUG: Assert When Calling AfxFreeLibrary from ExitInstance
ID: Q187684
|
The information in this article applies to:
-
Microsoft Visual C++, 32-bit Editions, versions 2.0, 2.1, 2.2, 4.0, 4.1, 4.2, 5.0
on the following platforms: Win95
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:
kbMFC, kbDLL, kbVC200bug, kbVC210bug, kbVC220bug, kbVC400bug, kbVC410bug, kbVC420bug, kbVC500bug, kbDSupport kbdsd
Keywords :
Version :
Platform : winnt
Issue type : kbbug