FIX: GetNextAssoc() Crashes _AFXDLL Application

Last reviewed: September 16, 1997
Article ID: Q105372
1.00 WINDOWS kbprg kbfixlist kbbuglist

The information in this article applies to:

  • The Microsoft Foundation Classes (MFC) included with:

        - Microsoft Visual C++ for Windows, version 1.0
    

SYMPTOMS

When using one of the map classes (for example, CMapStringToOb) and iterating through the map in a retail build of an _AFXDLL application, a general protection (GP) fault occurs in GetNextAssoc(). A debug build of the same application, or a non-AFXDLL version (debug or retail), does not cause a GP fault.

CAUSE

GetStartPosition() returns the predefined value BEFORE_START_POSITION, which is defined incorrectly in AFX.H. GetNextAssoc() does not identify this as the beginning of the map and incorrectly uses this value as a pointer.

RESOLUTION

Because an _AFXDLL application makes use of MFC200.DLL, it is insufficient to correct the definition of BEFORE_START_POSITION and rebuild the application. MFC200.DLL contains references to BEFORE_START_POSITION that were set at compile time (of the DLL), and therefore changing the definition without also rebuilding MFC200.DLL will not solve the problem. Microsoft does not recommend shipping modified versions of MFC200.DLL with applications.

To work around the problem, derive a new map class and override GetNextAssoc() by copying the code from the appropriate MAP_XX.CPP file in ~\MFC\SRC. No changes to the code are necessary, and it is not necessary to correct the definition of BEFORE_START_POSITION. Use the new map class in place of the original.

STATUS

Microsoft has confirmed this to be a problem with version 2.0 of the Microsoft Foundation Classes for Windows. This problem was corrected in MFC 2.5.

MORE INFORMATION

In AFX.H, BEFORE_START_POSITION is defined as:

   #define BEFORE_START_POSITION ((void*)(void NEAR*)-1)

The explicit NEAR cast in this definition combined with the large memory model (required by _AFXDLL) causes this to evaluate to DS:-1. The correct definition should be ((void*)-1), which does not depend on DS.

In a retail build, GetStartPosition() is an inline function, which causes it to exist in the application's code. This means that BEFORE_START_POSITION as returned by GetStartPosition() contains the application's DS.

On the other hand, GetNextAssoc() is not inline and exists in MFC200.DLL. Consider CMapStringToOb. On line 249 of MAP_SO.CPP is the comparison:

   if (pAssocRet == (CAssoc*) BEFORE_START_POSITION)

This comparison is intended to succeed when pAssocRet is the value returned by GetStartPosition(). However, BEFORE_START_POSITION in the above line contains the DLL's DS, and thus the comparison fails, in which case GetNextAssoc() proceeds to use pAssocRet, and a GP fault results.

When building a debug version of the application, inlining is turned off and both GetStartPosition() and GetNextAssoc() exist in MFC200D.DLL. For a non-AFXDLL application, both functions are linked into the application's code (both debug and retail). The same DS is used in all of these cases and GetNextAssoc() works correctly.


Additional reference words: 1.00 2.00 CMapWordToOb CMapWordToPtr
CMapPtrToWord CMapPtrToPtr CMapStringToPtr CMapStringToString
KBCategory: kbprg kbfixlist kbbuglist
KBSubcategory: MfcMisc
Keywords : kb16bitonly MfcMisc kbbuglist kbfixlist kbprg
Technology : kbMfc
Version : 1.00
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 16, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.