Solved

GDI memory leaks when using Palettes in Metafiles

Posted on 1997-12-12
6
657 Views
Last Modified: 2013-12-03
BoundsChecker throws up a memory leak error in GDI when using the following code

HDC      m_hrefdc, m_hmfdc;
HPALETTE hpal, psel;
RECT m_refrect;

m_hrefdc = CreateDC("DISPLAY", NULL, NULL, NULL);
m_hmfdc  = CreateEnhMetaFile(m_hrefdc, NULL, &m_refrect, "Test Metafile");
hpal     = CreatePalette( plogp );/** BOUNDSCHECKER ERROR **/
psel     = SelectPalette( m_hmfdc, hpal, FALSE );
DeleteObject( psel );

RealizePalette( m_hmfdc );
( perform GDI commands on metafile )

m_mfhndl = CloseEnhMetaFile(m_hmfdc);
( Use metafile )

DeleteEnhMetaFile(m_MetaFile)

The problem is that when the metafile is created, m_hmfdc is
invalidated, so the new palette cannot be selected out of it to be deleted.
Does anyone know of a workaround for this, or is it a
BoundsChecker artifact ?
0
Comment
Question by:dregan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1409457
Why would m_hmfdc be invalidated?
Where is the palette?  If you selected it into m_hrefdc then, you should be able to select it out.  It should not be invalidated.  At least not that I know of.
0
 
LVL 1

Expert Comment

by:ete
ID: 1409458
There is a very obvious memory leak according to your code fragment. You create a GDI object hpal, but you do not delete it. When ever you use CreatePalette() API, make sure you use DeleteObject() for the returned handle when you no longer need the object.

Also, depending on the handling of this code, there might be another problem as well. If this is from WM_PAINT or WM_ERASEBKGND for instance, you should not call DeleteObject() for the returned handle of SelectObject(). Instead after SelectObject() you do your things, then call SelectObject() again with the previously returned value and then call DeleteObject() for the palette you created.

Regards,
ETE
0
 

Author Comment

by:dregan
ID: 1409459
The hpal cannot be deleted because it is selected into the metafile DC.

The metafile DC is closed by the call to the CloseEnhMetafile(..) function (see MSDN documentation) --- this is where we would expect the palette memory to be freed.

If we selected the palette object out of  the metafile DC, in order to delete it, then the palette information in the metafile header would be wrong.
0
SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

 
LVL 1

Expert Comment

by:ete
ID: 1409460
Still not quite right. Whenever you use CreatePalette(), you must have a corresponding call to DeleteObject(), otherwise there is a memory leak. See CreatePalette() documentation. BoundsChecker correctly shows it to you. Your call to DeleteObject() is for wrong object and in wrong place.

CloseEnhMetaFile() does not delete the GDI object what you created, it just returns the handle for you to use. DeleteEnhMetaFile() releases the metafile handle, but again it does not delete the GDI object hpal that you created.

With the CreateDC() call you obtain the display device context, which you use as reference device context in your call to CreateEnhMetaFile()to create a metafile device context. The created/obtained reference dc should also be deleted with DeleteDC().

There seems to be a spelling mistake (I guess...) in the calls to CloseEnhMetaFile() and DeleteEnhMetaFile(). The returned handle from the previous call is what you should pass to the second call as a parameter.

More accurate code could look like:


HDC m_hrefdc, m_hmfdc = NULL;
HPALETTE hpal = NULL;
RECT m_refrect;
HENHMETAFILE m_mfhndl = NULL;

m_hrefdc = CreateDC("DISPLAY", NULL, NULL, NULL);
m_hmfdc = CreateEnhMetaFile(m_hrefdc, NULL, &m_refrect, "Test Metafile");

hpal = CreatePalette( plogp );
SelectPalette( m_hmfdc, hpal, FALSE );

RealizePalette( m_hmfdc );

( perform GDI commands on metafile )

m_mfhndl = CloseEnhMetaFile(m_hmfdc);

( Use metafile )

// release the metafile handle, same handle that was
// returned earlier
DeleteEnhMetaFile(m_mfhndl);

//destroy all created and not any more needed GDI objects
DeleteObject( hpal );
DeleteDC(m_hrefdc);
 
Regards,
Ete

0
 
LVL 1

Accepted Solution

by:
ete earned 250 total points
ID: 1409461
Still not quite right. Whenever you use CreatePalette(), you must have a corresponding call to DeleteObject(), otherwise there is a memory leak. See CreatePalette() documentation. BoundsChecker correctly shows it to you. Your call to DeleteObject() is for wrong object and in wrong place.

CloseEnhMetaFile() does not delete the GDI object what you created, it just returns the handle for you to use. DeleteEnhMetaFile() releases the metafile handle, but again it does not delete the GDI object hpal that you created.

With the CreateDC() call you obtain the display device context, which you use as reference device context in your call to CreateEnhMetaFile()to create a metafile device context. The created/obtained reference dc should also be deleted with DeleteDC().

There seems to be a spelling mistake (I guess...) in the calls to CloseEnhMetaFile() and DeleteEnhMetaFile(). The returned handle from the previous call is what you should pass to the second call as a parameter.

More accurate code could look like:


HDC m_hrefdc, m_hmfdc = NULL;
HPALETTE hpal = NULL;
RECT m_refrect;
HENHMETAFILE m_mfhndl = NULL;

m_hrefdc = CreateDC("DISPLAY", NULL, NULL, NULL);
m_hmfdc = CreateEnhMetaFile(m_hrefdc, NULL, &m_refrect, "Test Metafile");

hpal = CreatePalette( plogp );
SelectPalette( m_hmfdc, hpal, FALSE );

RealizePalette( m_hmfdc );

( perform GDI commands on metafile )

m_mfhndl = CloseEnhMetaFile(m_hmfdc);

( Use metafile )

// release the metafile handle, same handle that was
// returned earlier
DeleteEnhMetaFile(m_mfhndl);

//destroy all created and not any more needed GDI objects
DeleteObject( hpal );
DeleteDC(m_hrefdc);
 
Regards,
Ete

0
 

Author Comment

by:dregan
ID: 1409462
You're right. As soon as the CloseEnhMetafile(...) function has been called it is possible to delete the palette object. Thanks for the help.
0

Featured Post

Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
This article surveys and compares options for encoding and decoding base64 data.  It includes source code in C++ as well as examples of how to use standard Windows API functions for these tasks. We'll look at the algorithms — how encoding and decodi…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…

615 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question