FIX: Realloc with _AFXDLL Causes Assertion or GP Fault

ID: Q114986


The information in this article applies to:


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:


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 
Version           : 1.00 1.50
Platform          : WINDOWS 
Issue type        : 

Last Reviewed: July 27, 1999