FIX: Realloc with _AFXDLL Causes Assertion or GP Fault

Last reviewed: September 18, 1997
Article ID: Q114986
1.00 1.50 WINDOWS kbprg kbfixlist kbbuglist

The information in this article applies to:

  • The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++ for Windows, versions 1.0 and 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 reference words: 1.00 1.50 2.00 2.50
KBCategory: kbprg kbfixlist kbbuglist
KBSubcategory: MfcMisc
Keywords : kb16bitonly MfcMisc kbbuglist kbfixlist kbprg
Technology : kbMfc
Version : 1.00 1.50
Platform : WINDOWS
Solution Type : kbfix


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.

Last reviewed: September 18, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.