Is a memory leak possible with LoadIcon()?

delphi

Solution

You are calling `LoadIcon`. That returns what are known as shared icons. This is explained in the documentation for `DestroyIcon`. One of the consequences of being a shared icon is that you do not need to call `DestroyIcon`.

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, how does this relate to your code? Well, when you write

TrayIcon.Icon.Handle := LoadIcon(hInstance,'icon1');

you are assigning to the `Handle` property of a `TIcon` object. If that `TIcon` object already contains an icon, then that icon will be destroyed before being replaced by the new icon. That's because `TIcon` has ownership of its icon handles. All this means that the line of code above results in a call to `DestroyIcon` for a shared icon. This is what MSDN tells you not to do, but in fact it turns out to be benign. It's nothing to worry about.

Now, even if you were using a function that returns non-shared icons, e.g. `CreateIconIndirect` then your code would not leak icon handles. That's because the `TIcon` class takes on ownership of the icon handle.

But since you are using shared icons, it's not even possible to leak those handles. Objects that cannot be destroyed, cannot be leaked!

Some more points:

- I personally would not call `LoadIcon` over and over like that. I would call it twice at program startup and remember the shared icon handles. Then I would use those handles to assign to `TrayIcon.Icon.Handle`.

- When you call `LoadIcon` you do not have a lot of control over the size of the icon returned. I think that it's possible that you will get a large icon rather than a small icon. And that will need to be scaled to the small icon size before display. When creating notification area icons you should make sure that they are `SM_CXSMICON` by `SM_CYSMICON` sized.

Problem

I'm using this code to animate a tray icon in a thread (icon1 and icon2 are in a .res file): ``` while AnimationPending do begin TrayIcon.Icon.Handle := LoadIcon(hInstance,'icon1'); Sleep(300); TrayIcon.Icon.Handle := LoadIcon(hInstance,'icon2'); Sleep(300); end; ``` I have the fear that it may create a memory leak if I do it in a loop because icon1/2 are loaded all over again. Does the code create a memory leak, or is it safe to use in a loop?

Original source