FIX: Three Pens Leaked by MFC in Visual C++ 1.52

Last reviewed: September 18, 1997
Article ID: Q128604
1.52 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.52

SYMPTOMS

Running a 16-bit MFC application generated with Visual C++ version 1.52 under Windows results in a drop in the available GDI resources even after the application has exited. If you run under the debug kernel in Windows, you will see messages similar to these:

   wn PENLEAK GDI: Pen not deleted: 126A
   wn PENLEAK GDI: Pen not deleted: 1286
   wn PENLEAK GDI: Pen not deleted: 0E0E

Please note that this bug only exists in MFC version 2.52 that ships with Visual C++ version 1.52. The bug does not exist in previous 16-bit versions of MFC nor is it present in any 32-bit version of MFC.

CAUSE

Three GDI Pen objects are being created by MFC that are never destroyed. The creation of these objects can be found in the MFC source code in the file AUXDATA.CPP. They are:

   hpenBtnShadow = ::CreatePen(PS_SOLID, 0, clrBtnShadow);
   hpenBtnHilite = ::CreatePen(PS_SOLID, 0, clrBtnHilite);
   hpenBtnText = ::CreatePen(PS_SOLID, 0, clrBtnText);

RESOLUTION

If you are using the DLL version of MFC (building with _AFXDLL defined and linking with MFC250(d).LIB), then there is no way to work around the leak because this data is not exported from the DLL. However, if your project is statically linking to MFC, you will have an opportunity to delete these objects before your application (or _USRDLL) exits. This can be done in your application object's ExitInstance function.

First, you will need to get the handle to the pen objects that have not been deleted. These objects are members of the afxData structure defined in AUXDATA.H. If you include AUXDATA.H, you can get these handles and delete the pen objects in your ExitInstance function. This problem is specific to MFC version 2.52 and the workaround depends on using version-specific information, so you should compile the workaround conditionally depending on the version. For example:

   ...
   #if _MFC_VER==0x0252
     #include <..\src\auxdata.h>
   #endif
   ...

   #if _MFC_VER==0x0252
     extern void PASCAL _AfxExitDelete(HGDIOBJ hObject);
   #endif

   int CMyApp::ExitInstance()
   {

     #if _MFC_VER==0x0252

     _AfxExitDelete(afxData.hpenBtnShadow);
     _AfxExitDelete(afxData.hpenBtnHilite);
     _AfxExitDelete(afxData.hpenBtnText);

     #endif

     return CWinApp::ExitInstance();
   }

STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug was corrected in MFC version 2.52b included with Visual C++ version 1.52b for Windows.


Additional reference words: 1.52 2.52 bounds checker heapwalk
KBCategory: kbprg kbfixlist kbbuglist
KBSubcategory: MfcUI
Keywords : kb16bitonly MfcUI kbbuglist kbfixlist kbprg
Technology : kbMfc
Version : 1.52
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.