Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

GDI memory leaks when using Palettes in Metafiles

Posted on 1997-12-12
6
Medium Priority
?
679 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
  • 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
Fill in the form and get your FREE NFR key NOW!

Veeam is happy to provide a FREE NFR server license to certified engineers, trainers, and bloggers.  It allows for the non‑production use of Veeam Agent for Microsoft Windows. This license is valid for five workstations and two servers.

 
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 750 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

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

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

This article describes how to programmatically preset the "Pages per Sheet" option that's available with most printer drivers.   This setting lets you do "n-Up" printing, where two, four, or more pages are printed on each sheet of paper. If your …
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
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…

926 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