Solved

GDI memory leaks when using Palettes in Metafiles

Posted on 1997-12-12
6
648 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
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
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

Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

Question has a verified solution.

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

Suggested Solutions

This article shows a few slightly more advanced techniques for Windows 7 gadget programming, including how to save and restore user settings for your gadget and how to populate the "details" panel that is displayed in the Windows 7 gadget gallery.  …
If you have ever found yourself doing a repetitive action with the mouse and keyboard, and if you have even a little programming experience, there is a good chance that you can use a text editor to whip together a sort of macro to automate the proce…
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…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

821 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