Run this program several times in Windows 98:
This message then occurs when you try to start Explorer or other programs - and persists after you exit from the program.that loaded the cursors.
You then have to reboot Windows to continue
Introduction
LoadImage
is the routine used to load images, bitmaps and cursors. The help for this routine says that it cleans up resources on exit, but is a bit vague in what it says about memory. Normally Windows cleans up memory too on exit, but in some circumstances it seems that it fails to do so for LoadImage
.
The observations may have other explanations. What you have to do is to first load a huge number of cursors using LoadImage
. When you try to start another program you get out of memory messages, or access violations or GDI errors - so far this is not so suprising perhaps. However, the messages persist after you exit from the app that caused them in the first place. The only solution then is to reboot to continue working.
Background
The help for LoadImage
says: The system automatically deletes these resources when the process that created them terminates, however, calling the appropriate function saves memory and decreases the size of the process's working set. (My emphasis).
What does saves memory mean here? I haven't found any information about the cause for it anywhere, though on-line searches bring up a few pages with comments by coders who have found this leak and developed work arounds for it. The situations that make the leak noticeable are fairly rare but not that unusual - for instance if you accidentally leave out the LR_SHARED
flag and load a cursor repeatedly, then your app will not only run out of memory for the cursors eventually, but when it does so the user will be forced to reboot to continue
The memory leak isn't detected by standard memory leak detectors such as the one built in to MSVC.
Using the code
Here is the code that causes the memory leak:
for (i = 0; i < 50000; i++)
{
hCursor = (HCURSOR) LoadImage(hInstance, "cursor1",
IMAGE_CURSOR, 0, 0,
LR_DEFAULTSIZE);
if(!hCursor)
break;
}
You may need to wait a little while for all the cursors to load. Run this program. You may well get out of memory errors of course if you then try to run another program while this one is running. However, exit from it and then see if they persist. If not, try running it maybe half a dozen times. If you still get no errors after it has exited then probably your setup doesn't have this problem.
This happens in Win 98 and I'm told it also happens in Win 2K.
I also tried the test with bitmaps.
for (i = 0; i < 50000; i++)
{
HBITMAP hBitmap = (HBITMAP) LoadImage(hInstance, "10MB_BITMAP",
IMAGE_BITMAP, 0, 0, 0);
if (!hBitmap)
break;
}
No memory leak error messages occurred after exiting from this program in Windows 98. I ran the test program several times. However I understand it can cause leaks in Windows ME. I hope other members will respond to this article with details for the other operating systems.
Points of Interest
The first important point is to make sure you use LR_SHARED
for cursors and icons where it is possible (this flag can only be used for standard size resources, can't be used if you load the resource from a file, and can't be used for bitmaps since they are not of a fixed standard size).
The best solution is to keep handles for all the cursors you load and destroy them explicitly when your program exits, and ditto for icons and images. The observations so far (though not conclusive) seem to suggest that if you can't use the LR_SHARED
flag you should always destroy these resources explicitly if your program is likely to be used in Windows 98 or Win 2K.
Although the problem showed up in a situation where a bug caused a program to load thousands of copies of a cursor (once for every frame of an animation), I don't know whether or not it will also occur if you load just a single cursor or a few custom cursors. Does the use of LR_SHARED
prevent the leak? If it does then fine, as most uses of the routine will set the flag LR_SHARED
. But if not, then since nearly all Windows programs rely on automatic freeing of custom cursors on exit, then it means that nearly every time you run a program with custom cursors in Windows 98 or 2K, you are leaking a few hundred bytes of memory, maybe even a few KB if it has a fair number of them! In the case of a computer that is on 24/7 for months, that would add up eventually.
Also the out of memory message happens after you load maybe 5,000 or so cursors at 326 bytes each - but if it is indeed a memory issue one would expect to need to load millions of cursors before one notices anything, at least if one has several hundred megabytes of RAM installed. There I can think of two possibilities so far - that it is a memory fragmentation issue, so that many small allocations are worse - or that it is really some kind of resource issue getting reported as a memory allocation problem in the error messages from Windows.
Another interesting note - in Windows 98 SysMon shows the memory as freed when you exit from the program even though the out of memory messages persist at that point. Does this mean it is a resource issue, or is it because the memory is still allocated but for some reason not reported in the system monitor? The observation that it also happens in Win 2K suggest it might be a memory issue rather than a resource issue.
If anyone has any information about this or further observations, please share it with the rest of us. Thanks!
History
First release.
Related article
Check for and free memory leaks