News:

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

HeapAlloc: Need to free on exit?

Started by jj2007, January 13, 2009, 10:06:06 PM

Previous topic - Next topic

jj2007

Since this is a newbie question, I post it in the Campus:

Is it necessary to free memory on ExitProcess?

I tried googling it up, and looked in MSDN, but could not find any crystal clear rule. So I wrote the snippet below, and called it a thousand times, apparently without any problems. Is it a documented / known behaviour of Windows (XP in my case) to free automatically memory allocated on the heap?

include \masm32\include\masm32rt.inc

.code
hw db "Hello World", 0

start:
invoke GetProcessHeap
.if eax==0
MsgBox 0, chr$("GetProcessHeap failure"), offset hw, MB_OKCANCEL
.else
invoke HeapAlloc, eax, HEAP_GENERATE_EXCEPTIONS, 100000000
.if eax==0
MsgBox 0, "HeapAlloc failure", offset hw, MB_OKCANCEL
; .else
; MsgBox 0, "Heap allocated", offset hw, MB_OKCANCEL
.endif
.endif
invoke ExitProcess, eax

end start

zooba

Short answer, no.

All createable objects (including memory allocations) are tied to the process that creates them. When that process dies, everything is freed. I read once that you should still do your own cleanup, because the automatic cleanup is far from optimised (and there's no point optimising for poorly written programs when you could be optimising for well written programs), I think this was at Raymond Chen's blog, but couldn't find the actual reference.

The Heap* functions are effectively a large contiguous allocation (VirtualAlloc-style), so freeing all allocations is as simple as freeing the page(s) used (see HeapDestroy). Global* and Local* also operate on a private heap (see Global and Local functions) and presumably have similar behaviour. File maps (recommended for cross-process communication) are reference counted.

In general, a process can do anything it likes within itself. When it closes, it all disappears. (Obviously this doesn't apply to modifying system settings/registry/etc.)

Hope that answers your question.

Cheers,

Zooba :U

jj2007

Thanks a lot, Zooba. Eventually I found this Quick overview of how processes exit on Windows XP in Raymond's blog - a must-read, quote:
"Using the word design to describe the way processes exit on Windows XP is like using the term swimming pool to refer to a puddle in your garden."

So it seems I can safely skip the HeapFree call. I would be less confident regarding other handles, since I managed countless times to freeze my system through exits not taking care of GDI etc handles. Win XP has lots of these beasts, therefore most of the time you would not notice such leaks, but it took me years to chase down one which manifested itself only after a hundred or so launches of that particular program.

zooba

Quote from: jj2007 on January 13, 2009, 11:27:43 PM
Eventually I found this Quick overview of how processes exit on Windows XP in Raymond's blog - a must-read

I had that link in my original answer, but since it wasn't the article I was thinking of I dropped it.

Do keep in mind that it's only at the very end of the program (or when the heap is destroyed through HeapDestroy) that you don't have to free every allocation. If your application runs for a long time without deallocating any memory you will eventually crash (whether from lack of address space or lack of hard drive (for the page file)).

Cheers,

Zooba :U

jj2007

Quote from: zooba on January 14, 2009, 02:32:59 AM
If your application runs for a long time without deallocating any memory you will eventually crash (whether from lack of address space or lack of hard drive (for the page file)).

I was looking for an elegant way to allocate one big fat buffer at startup - and then forgot about it. There is the crtbuf macro, see below, but it shows a somewhat inconsistent behaviour at assembly time. Sometimes it doesn't delay assembly at all, sometimes it slows it down by some seconds, which can be quite a nuisance.


include \masm32\include\masm32rt.inc

crtbuf MACRO NameOfVar, BufLen
LOCAL lbl, lblE
.data?
  align 4
  lbl LABEL byte
  ORG $+BufLen-1
  db ?
  .data
NameOfVar dd lbl ;; define it in the data section
  .code
ENDM

.code

start:
crtbuf MyFatBuffer, 10000000
MsgBox 0, "Ten MB allocated", "crtbuf macro:", MB_OK
exit

end start


zooba

For a buffer of that size, I'd use VirtualAlloc.

Chances are you can just forget about it, though from a good programming perspective I wouldn't.

.data?
    pBigBlock DWORD ?

.code
Start:
    invoke VirtualAlloc, NULL, 10000000, MEM_COMMIT, PAGE_READWRITE
    mov pBigBlock, eax

    call Main

    invoke VirtualFree, pBigBlock, 0, MEM_RELEASE

    invoke ExitProcess, 0


The VirtualFree call really isn't a big enough deal to just forget about it, IMHO.

Cheers,

Zooba :U