News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How to avoid leaky Windows programs

Started by NoCforMe, October 23, 2011, 03:00:17 AM

Previous topic - Next topic

NoCforMe

I know it's possible to create Windows apps that "leak" memory (i.e., allocate memory but don't deallocate it on exit), and I want to avoid this problem, of  course.

Up to now I've been pretty much breezily going on the assumption that all of the objects I create (mostly handles, to brushes, windows, etc.) will be automagically deallocated upon exit. I am careful to deallocate explicitly allocated memory (i.e., using GlobalAlloc() ). But is this correct?

I know it's probably a big question, possibly a big can of worms, but are there any (more or less) simple guidelines as to what objects one needs to destroy or deallocated before exiting a program?

Thanks especially to any Windoze experts who may happen to wander by here ...

jj2007

> will be automagically deallocated upon exit
That is the Common Wisdom, although MSDN is somewhat half-baken about it, documentation-wise. I have had several occasions where after allocating a lot of heap mem (>500 MB) and exiting with a crash, the whole system was so slow that I had to reboot.
If you want to test it, write a proggie that misbehaves, and launch it a thousand times. Report what happens :bg

dedndave

allocated memory is easy to understand
if you allocate it - free it when done
a similar statement can be made for file handles, of course

the stack space you use - don't worry about it - ExitProcess releases it for you

beyond that, i suggest you carefully read the documentation for each function you use that returns a handle
in many cases, destroying the window releases the handles
in some cases, it does not
font handles come to mind - they usually need to be deleted  :P

brush handles - it depends on how it is created and used

for example, if you get a handle to a stock object (GetStockObject),
the handle does not need to be deleted, but there is no harm in doing so

if you use a system color in WNDCLASSEX (the first 19 values or NULL) - RegisterClassEx accepts an index - no handle to delete
if you use a system color above the first 19 (CreateSolidBrush), it should be deleted
if you use the same brushes by obtaining a handle during WM_PAINT (GetSysColorBrush), you must not delete it

menu handles are on and off, too - lol
if the menu handle is set to a window (SetMenu), the handle does not need to be destroyed
otherwise, it should be

the point is - each case is different, and you have to do a little research and reading

NoCforMe

OK, I went back and checked, and the description of CreateFont() does say, in the Remarks section:

Quote
When you no longer need the font, call the DeleteObject function to delete it.

so that does seem like a Good Idea. However, it seems there are a lot of murky cases where MSDN doesn't really make it clear whether or not you are supposed to destroy/delete/deallocate the object.

Further research is called for.

dedndave

you get a lot of info of this kind by reading the general catagory docs
like the About Menus, Using Menus, Using Brushes, etc - those sections

also - read the sections about creating windows
and - the DestroyWindow function probably has some info

hutch--

Apply the law of gravity, what goes up must come down. You can be sloppy with simple stuff and it gets recovered on exit but get used to deallocating memory that you allocate once you have finished with it or it can come back and bite you when you least expect it.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

The recommendations on DeleteObject refer to running processes. If you create fresh brushes in a WM_MOVE handler, then after some hours the user might get new experiences indeed. But quitting the app is a different case.

> The ExitProcess function in the __except block automatically releases virtual memory allocations

The Master's Voice... I am pretty sure that all those cute fonts and brushes and controls etc reside somewhere in the heap and get discarded with ExitProcess. The question is what happens if you exit the process your own wayTM (and NoCforMe has repeatedly indicated that he wants to do everything his own way :green2)

ToutEnMasm


If you want to be sure that all  is free , put a zero on all variables with a free hAndle.
On exit , verify that all variables with an handle have  zero value.
Doing this , you win another advantage in complex loop.Is it done ?,look the value of handle values,if it is zero,you have to init them.
You can also group them in data.

NoCforMe

Quote from: jj2007 on October 23, 2011, 06:31:25 AM
> The ExitProcess function in the __except block automatically releases virtual memory allocations

The Master's Voice... I am pretty sure that all those cute fonts and brushes and controls etc reside somewhere in the heap and get discarded with ExitProcess. The question is what happens if you exit the process your own wayTM (and NoCforMe has repeatedly indicated that he wants to do everything his own way :green2)


Well, while that may be true (and don't we all here have our various idiosyncrasies for that matter?), I do use ExitProcess() to bring the whole thing to a screeching halt. How else would you do it?



start:
INVOKE GetModuleHandle, NULL
MOV InstanceHandle, EAX

INVOKE WinMain, EAX
INVOKE ExitProcess, EAX



Which I copied out of the MASM32 example programs.


jj2007

Quote from: NoCforMe on October 23, 2011, 07:06:34 AM...use ExitProcess() to bring the whole thing to a screeching halt. How else would you do it?

Ask Dave for his favourite exception :bg

dedndave

 :bdg
not just my favourite - everyones favourite is c0000005 - access violation   :bg
when i started out, i considered changing my forum nic to c0000005 - lol

JJ's msdn link is a good one
i found another....
http://msdn.microsoft.com/en-us/library/ms859400.aspx

and i found a couple programs
these programs may not detect all leaks, but can be helpful
http://winleak.sourceforge.net/
http://www.runtimechecker.com/

haven't tried the first one - but i will play with it
the second one - i have used it
it basically checks to see if you've crossed all your T's and dotted all your I's

jj2007

Quote from: dedndave on October 23, 2011, 10:00:53 AM
i found another....
http://msdn.microsoft.com/en-us/library/ms859400.aspx

"Typically, the operating system can clean up after a program which leaks memory after it terminates."

But: expected != observed behaviour :naughty:

dedndave

that's for sure - lol

Quote"Typically, the operating system can clean up after a program which leaks memory after it terminates."

they must be talking about some OS other than windows   :lol

redskull

You are really talking about two different things: executive objects and virtual memory.  Whenever a process ends, all it's memory is freed and given back to the system; since the process heap exists in the process memory, there is no worry about leaking that (i.e. VirtualAlloc, HeapAlloc, GlobalAlloc, etc).

Executive objects, basically anything that you have to create via a function and access via a HANDLE (fonts, mutexes, files, etc), are managed by the operating system; that's why you have to access them indirectly using a handle, and not directly via a pointer.  Objects that exist in the system are reference counted by the kernel, and remain active until all the processess using them no longer do so.

However, each process keeps a list of all the handles a particular process has opened (0x0dc in the EPROCESS block).  Part of the shutdown that happens when your process ends is that these still-open handles are closed, so generally speaking, any memory those objects are taking up will not leak.  That being said, however, certain objects are 'permenent'; they are not reference counted and will stay active until you explicity release them.  I can't recall exactly which ones are, but there is an OBJ_PERMANANT attribute you can check to see.  IIRC, these are few and far between.

All that aside, however, delete stuff when you no longer need it.  Just because it will probably get freed when you end your process doesn't mean it won't have negative affects while you ARE executing; each object you create still tags YOUR memory usage quota.  If you leave outstanding objects created, then you will take more paging hits, etc. 

But in the end, it's just bad programming: clean up your own mess.

-r
Strange women, lying in ponds, distributing swords, is no basis for a system of government

jj2007

Quote from: redskull on October 23, 2011, 04:45:21 PM
You are really talking about two different things: executive objects and virtual memory.  Whenever a process ends, all it's memory is freed and given back to the system; since the process heap exists in the process memory, there is no worry about leaking that (i.e. VirtualAlloc, HeapAlloc, GlobalAlloc, etc).

red,
I wish this were true, but my experience says if you crash your app, you will have to reboot to make your system fast again - Win XP SP3.
Re bad programming habits: if there is a clear documentation saying ExitProcess does all the cleanup, then it is bad programming to do the same before ExitProcess. Nonetheless the Exit (uppercase E...) macro of MasmBasic cleans all allocated memory and closes all open filehandles. Precisely because the documentation is so lousy, and because my experience says don't trust the OS.