Click to See Complete Forum and Search --> : HICON resource leak, yes or no


Zeddy2
September 28th, 2005, 06:52 AM
Hi guys...

Code is:

void SetIcon()
{
HICON hFolderIcon = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON_FOLDER), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR );
GetDlgItem(IDC_BUTTON_OMGWTFLOL)->SendMessage(BM_SETIMAGE, IMAGE_ICON, (LPARAM)hFolderIcon);
}

Yes that is MFC related but this is win32 question. Note scope of LoadImage().

Now I originally believe that cause hFolderIcon is created on stack, then handle is used to set icon on button, windows deletes GDI object when button is destroyed. Even though hFolderIcon goes out of scope & gets destoryed in code, icon is still on button, so I always believe that windows deletes GDI object and no gdi resource leak happen.

Now today I do this code and run through Devpartner instrumentation. If you not know what this is, it like Boundschecker on drugs. Part of Devpartner detect memory and resource leak in code. So if you code this:

void func()
{
char* blah = new char[MAX_PATH];
}

This obvious a mem leak - Devpartner instrumentating finds it and reports it after runtime. Devpartner do this for everything - COM object, handles etc.

Now when I run above code (HICON code) through devpartner, it says I have memleak for GDI object even though it gone out of scope.

So devpartner believes win32 does not destroy gdi handle when button is destroyed = mem leak. I believe win32 does destroy gdi handle = no mem leak.

I not refer to gdi object cleanup/ garbage collection, i refer to explcit handling of object, if that make sense.

Which is right? :)

wildfrog
September 28th, 2005, 07:07 AM
I believe this:


Remarks

It is only necessary to call DestroyIcon for icons and cursors created with the following functions: CreateIconFromResourceEx (if called without the LR_SHARED flag), CreateIconIndirect, and CopyIcon. Do not use this function to destroy a shared icon. A shared icon is valid as long as the module from which it was loaded remains in memory. The following functions obtain a shared icon:

- LoadIcon
- LoadImage (if you use the LR_SHARED flag)
- CopyImage (if you use the LR_COPYRETURNORG flag and the hImage parameter is a shared icon)
- CreateIconFromResource
- CreateIconFromResourceEx (if you use the LR_SHARED flag)

So, since you're calling LoadImage without the LR_SHARED flag, maybe you should call DestroyIcon as well...

- petter

PadexArt
September 28th, 2005, 07:45 AM
Yes you need to. Here is a MSDN sample (http://support.microsoft.com/default.aspx?scid=kb;en-us;142226) that shows explicit deletion.

Zeddy2
September 28th, 2005, 09:57 AM
Grah. Thank you kindly. Devpartner saves day again...

While I here, wildfrog:

It is only necessary to call DestroyIcon for icons and cursors created with the following functions:

Yes loadimage is not in one of those functions :D

Write clear documentatiion, **** microsoft!

kirants
September 28th, 2005, 12:15 PM
Yes that is MFC related but this is win32 question. Note scope of LoadImage().

Now I originally believe that cause hFolderIcon is created on stack, then handle is used to set icon on button, windows deletes GDI object when button is destroyed. Even though hFolderIcon goes out of scope & gets destoryed in code

hFolderIcon is not a memory location. So, the question of whether it is on the stack or not doesn't arise.

You need to understand that memory leak and resource leaks are 2 different things. Memory leaks are memory allocated on heap but not released.. i.e. if you keep doing new , new, new or malloc .. malloc etc.. and don't delete/free.. the heap manager would have expanded the heap and at the time of program exit, you would see that the heap manager hasn't reclaimed that allocated memory back.. That is referred to as memory leak.

However, resource leaks are different.. You allocated resources with APIs similar to LoadImage/CreateBitmap etc.. They return you handles , but they aren't pointing to memory location as such.. Picture it as the handles being a simple 4 bytes of some kind of number.. ( what that number is not important and it is the WIndows' resource manager's work to understand what it is and what it represent ). Just look at it as a magic number you use to represent a particular resource. Now, how windows knows to free the resource associated with that number is when you call something like DeleteObject and such cleanup APIs, wherein you pass the number back..

So, even though you have called
hFolderIcon = LoadImage.. and the function has exited and hFolderIcon is gone out of scope, nothing much has happened. LoadImage has allocated some resource for the icon and returned you a number. Now, even if hFolderIcon has gone out of scope that number and the resource allocated is still there... SO, it is your responsibility to free them up using approproate APIs like DeleteObject.. CloseHandle() etc..

The MSDN documentation is clear on when you should use DeleteObject and when you needn't ( for example you don;t have to free Stock objects ).

When it comes to MFC, the scope of the variable can have a say.
example:

Somefunction()
{
CFont oFont;
oFont.CreateFontIndirect... ();
m_oEdit.SetFont(&oFont);
}


Here, you will have no resource leak. Reason being, oFont goes out of scope on function exit. When it does, CFont destructor will be called and one of the things the destructor does is

CFont::~CFont()
{
if(m_hFont)
::DeleteObject(m_hFOnt);
}

//where m_hFont is initialized when CreateFontIndirect is called.

While this is good as far as resource leak is concerned ( there is none in this case ), the font is destroyed on fucntion exit and so, the edit control will have an invalid font set.