FIX: Realloc with _AFXDLL Causes Assertion or GP FaultID: Q114986
|
A call to realloc() or _frealloc() from a debug build of an extension DLL
(a DLL that uses the _AFXDLL version of MFC) causes the following to occur:
In MFC, version 2.0, the debug version of AfxAppReAlloc() does not call the
application's debug memory allocation routines [AfxAppAlloc() and
AfxAppFree()]. Instead, it calls only realloc().
When malloc() is first called to obtain memory, the debug allocator
[AfxAppAlloc()] is used, which adds an entry to the Framework's list of
allocated memory blocks. However, realloc() simply frees the memory without
making a change to the list of memory blocks. This causes a GP fault when
further allocations are made because the framework's list of allocated
memory blocks has an entry that points to an already freed block of memory.
In MFC, version 2.5, the implementation of _frealloc (in AFXDLLX.H) fails
to set a stack-based Boolean value [bAllocObj()], which indicates whether
the application's memory allocator should use "global new" or "CObject
new". If the previous allocation or deallocation was done with CObject new
or "CObject delete," the Boolean variable is set to "TRUE" and the
subsequent call to realloc() fails to set it to "FALSE". This forces
CObject delete to be called on a block of memory that was not allocated
with CObject new. The comments above line 163 in AFXMEM.CPP explain that
the assertion failure is because of this problem.
The problem only occurs in a debug build. The debug implementation of AfxAppReAlloc() calls only AfxAppAlloc(), copies the memory, and then calls AfxAppFree(). You can work around the problem by using conditional compilation to call malloc() and free() when doing a debug build. For example, change
pNew = realloc(pOld,300)
to the following:
#ifndef _DEBUG
pNew = realloc(pOld,300);
#else
pNew = malloc(300); // This ends up calling AfxAppAlloc
memcpy(pNew,pOld,300);
free(pOld); // This ends up calling AfxAppFree
#endif
If you are using MFC, version 2.5, you can make a change in the _AFXDLL
include file, AFXDLLX.H (see "MFC TechNote 33" for information on
this file), which is installed in \MSVC\MFC\INCLUDE by default.
The change would be to modify the _frealloc() function so that
it properly changes the Boolean variable. The _frealloc() function
should be changed to the following:
extern "C"
void __far* __cdecl _frealloc(void __far* pOld, size_t nSize)
{
#ifdef _DEBUG
ASSERT(_AfxGetAppData()->lpfnAppReAlloc != NULL);
_AfxGetAppDebug()->bAllocObj = FALSE;
#endif
return (_AfxGetAppData()->lpfnAppReAlloc)(pOld, nSize);
};
After you make the change, choose Rebuild All from the Project menu. You
must choose Rebuild All because you can't just recompile the module that
calls realloc(); you must rebuild the module that includes the header file
AFXDLLX.H.
Microsoft has confirmed this to be a bug in the Microsoft
Foundation Classes, versions 2.0 and 2.5. This bug was corrected in MFC
version 2.51, included with Visual C++ version 1.51.
This problem does not occur with Visual C++ 32-bit Edition.
Additional query words: 1.00 1.50 2.00 2.50
Keywords : kb16bitonly kbnokeyword kbMFC kbVC
Version : 1.00 1.50
Platform : WINDOWS
Issue type :
Last Reviewed: July 27, 1999