Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does windows reclaim stack space?

Tags:

c

stack

windows

I am doing a technique called "stack painting". To determine how much stack space a particular function utilized.

If I allocated 1MB worth of items on the stack. And then am sure that I am not using any of those items off the stack. Does windows automatically decommit (free) those unused pages?

I am wondering specifically about the VMM of Windows. Regarding if the page is committed or not necessarily comitted but just reserved?

In otherwords, if I manually access the memory down to that 1MB may windows throw an Access Violation?

like image 886
unixman83 Avatar asked Jan 20 '23 05:01

unixman83


2 Answers

You don't delete stuff that's allocated on the stack; it gets automatically reclaimed, since when you exit from the current scope the stack pointer is moved back to the previous stack frame1, so all the memory used in for objects in the current scope is effectively reclaimed.

In line of principle, all the stack is allocated when the application is loaded in memory, so it's a structure of fixed size that gets reused over and over (while the code flow moves in and out of scopes); the OS may play clever tricks (by using guard pages to commit the upper parts of the stack, that were just reserved on the start of the application), but in general this shouldn't concern you.

The stack size is a part of the PE header (the header of your executable), and you can set it with a linker option. You can retrieve such value for a loaded executable by snooping in the PE structures loaded in memory (basically its HMODULE is the location where the executable file is mapped in memory); I think that the ImageHelper library can be useful in this task.


  1. Naturally, after the destructors are run; by the way, FPO can change the things a bit here, but the concept remains the same.

Edit

In otherwords, if I manually access the memory down to that 1MB may windows throw an Access Violation?

If it's already been committed (i.e. you allocated and deallocated your 1 MB of objects on the stack), I don't think it can happen.

Windows wouldn't have a clue that that part of the stack is no longer in use. Windows can detect if it has to commit more pages, using guard pages to detect access to the upper part of the stack, but it can't know that those pages aren't used anymore.

Actually it could look up the stack pointer at context switch, but it would break apps that do "clever" things with the stack, and in general it would be an optimization that isn't worth the effort: if there's no memory those pages can still be paged out.

Still, to play it safe (e.g. if you don't know if that allocation has taken place) you should read the stack going from the currently used section upwards, so if the pages upwards haven't been committed yet you would still touch the guard page, alerting Windows to commit more pages for the stack.

like image 82
Matteo Italia Avatar answered Jan 30 '23 23:01

Matteo Italia


To answer your first question, no Windows does not decommit those pages. Any pages that were committed as the stack grew remain so until the thread terminates.

To answer your second question, the relevant fields are in the IMAGE_OPTIONAL_HEADER32 or IMAGE_OPTIONAL_HEADER64 structure. They are SizeOfStackReserve and SizeOfStackCommit. This structure is part of the NT header of the PE, which in turn is referenced from the MSDOS header (the thing that starts at offset 0 in a PE with "MZ" as a magic value).

Microsoft's link.exe has the "/STACK:reserve[,commit]" switch which directly correlates to these two fields.

Edit since the question changed: you can only reliably access the committed pages of the stack and the current guard page. You should expect an AV if you access a reserved page that isn't the guard page (if you access the last guard page, you'll get a SEH stack overflow exception).

like image 43
Peter Huene Avatar answered Jan 30 '23 23:01

Peter Huene