Microsoft KB Archive/114986

{|
 * width="100%"|

FIX: Realloc with _AFXDLL Causes Assertion or GP Fault

 * }

Q114986

-

The information in this article applies to:


 * The Microsoft Foundation Classes (MFC), included with:
 * Microsoft Visual C++, versions 1.0, 1.5

-

SYMPTOMS
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.5: an assertion failure takes place in AFXMEM.CPP, line 363.
 * In MFC, version 2.0: the heap is corrupted, which generally causes a GP fault during subsequent allocations.

CAUSE
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.

RESOLUTION
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.

STATUS
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

Issue type :

Technology : kbAudDeveloper kbMFC