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

ID: Q128604

1.52 WINDOWS kbprg kbfixlist kbbuglist

The information in this article applies to:

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 kbMFC KbUIDesign kbVC kbbuglist kbfixlist
Version           : 1.52
Platform          : WINDOWS
Solution Type     : kbfix

Last Reviewed: September 21, 1997