Stack and Heap

Started by
10 comments, last by bakery2k1 17 years, 6 months ago
Hey, I would like to get a more thorough understanding of memory allocation and execution of my programs. I was wondering if there is any way of looking at what is contained on the stack and the heap for a program that i write using dev-c++? or any other tool for that matter? Thanx
Advertisement
Dev-C++? So you're asking about Windows?

The NT_TIB structure contains the base address of the stack (top) as well as the current bottom (Win32 Thread Information Block, Under The Hood - MSJ, May 1996). You ought to be able to read contents of that range of addresses. To be on the safe side, check the pointers using IsBadRead (and friends) before dereferencing them.

Also look into the VirtualQuery function. You can use this to traverse the entire user space range of a process address space. That would be 0x00000000 to 0x7FFFFFFF. This includes the stack and the heap. The information returned by that function can help determine whether an address is valid or not as well.

The value returned by GetProcessHeap is the address where the default process heap begins. It's not the same a the CRT heap, but it's readable too.

And if you really want to get into the nuts and bolts of virtual memory under Windows, check out: Memory Management: What Every Driver Writer Needs to Know as well as the Intel IA32 Processor manuals.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Sweet thanx man :D guess I got a bit of reading to do.
Was hoping for some sort of stack emulator thing but I guess I could make my own after reading all this stuff.
Why emulate when you can look at the real thing?

Using Dev-C++, you can use GDB to debug. GDB has the fine "x" command that lets you look at arbitrary addresses.

With MSVC, it's even easier (download the free version of MSVC++ Express if it's still available); the debugger has a scrollable, interactive Memory View window.

Just stop at a breakpoint and look to your hearts content!
enum Bool { True, False, FileNotFound };
A debugger, perhaps? Never used any to step through at the source code level other than Visual Studio's, but if you have a passing knowledge of assembly (not really needed, to be honest) and how the stack works then almost any one would do - and with that in mind, I'd like to recommend OllyDbg.

EDIT: It's too late, and I'm too slow for these forums!
[TheUnbeliever]
I second the OllyDbg proposal. The amount of knowledge you can gain from debugging a single executable in OllyDbg is colossal. It strikes a perfect balance between user-friendliness and raw power - I wouldn't trade my Olly for anything.

That said, there really isn't much to memory allocation. Certainly not on a release build. A brief outline:

Stack: Local objects, Function parameters, Return addresses, SEH frames
.data Heap: Global & static variables, initialised variables
Extended Heap: Dynamically allocated objects
.rsrc: Resources
.bss: System-wide shared memory

Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:To be on the safe side, check the pointers using IsBadRead (and friends) before dereferencing them.


Remember that IsBadXxxPtr should really be called CrashProgramRandomly. Poking around in the stack using it is very likely to cause the "hit a guard page" problem.

Quote:
Stack: Local objects, Function parameters, Return addresses, SEH frames
.data Heap: Global & static variables, initialised variables
Extended Heap: Dynamically allocated objects
.rsrc: Resources
.bss: System-wide shared memory


.data is not a heap, but a section of your executable file. You are correct in stating that it holds initialized global and static variables.

The .bss section contains your application's uninitialized (and, AFAIK, zero-initialized) global and static variables. It is not shared, but process-private. The reason it is separate from the .data section is that since the initial values of its contents are zero, they do not need to be stored explicitly within your executable.
Quote:Original post by bakery2k1
Quote:To be on the safe side, check the pointers using IsBadRead (and friends) before dereferencing them.

Remember that IsBadXxxPtr should really be called CrashProgramRandomly. Poking around in the stack using it is very likely to cause the "hit a guard page" problem.


Interesting, and recent too September 27, 2006. Too bad MS let it ride for all those years...
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by bakery2k1
.data is not a heap, but a section of your executable file. You are correct in stating that it holds initialized global and static variables.

I'm fully aware of this, but in my experience, high-level programmers tend to lump everything into either 'stack' or 'heap'. Since this section is entirely dissociated from the stack, I figured it would be best to bend truth and throw it in with the heap storage. The .data section, of course, cannot grow dynamically and so it doesn't qualify as a heap, but it's treated in much the same way from the coder's perspective.

As for the .bss issue, it seems I had totally the wrong end of the stick. In my defense, no widely-used compilers have been known to create uninitialised data storage, and aren't likely to in future. I've never actually seen a .bss section [sad]. Nevertheless, I stand corrected.
I'm sure you'd have guessed this, but the bss section is zero-initialised, but only because ntdll's process-loading routines initialise memory to zero by default. Of course, this isn't part of the PE specification, and so it can't be relied on, so technically this section is indeed uninitialised.

Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by TheAdmiral
in my experience, high-level programmers tend to lump everything into either 'stack' or 'heap'


True, but I wish they wouldn't. "Name and describe the memory areas used by your program" seems to be quite a common job interview question and of course, the first time I was asked it, I got it wrong on this particular point.

Quote:
no widely-used compilers have been known to create uninitialised data storage, and aren't likely to in future.


Of course widely used compilers create .bss sections for uninitialized (or zero-initialized) variables. Consider the following code:

unsigned char array[0x1000000] = {0};int main(){	return 0;}


The resulting object file (and executable file) do not contain a 16MB chunk of zeros in their data section to represent "array". Rather, they contain an entry in their section header table stating that there is a 16MB BSS section, which is to be zero-initialised. Here is the output of objdump -h for the corresponding object file (compiled with gcc):
Sections:Idx Name          Size      VMA       LMA       File off  Algn  0 .text         00000040  00000000  00000000  0000008c  2**4                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE  1 .data         00000000  00000000  00000000  00000000  2**4                  ALLOC, LOAD, DATA  2 .bss          01000000  00000000  00000000  00000000  2**4                  ALLOC
Here is the corresponding dump when compiled with MSVC:
Sections:Idx Name          Size      VMA       LMA       File off  Algn  0 .drectve      0000002a  00000000  00000000  000000b4  2**0                  CONTENTS, READONLY, DEBUGGING, EXCLUDE  1 .debug$S      0000007e  00000000  00000000  000000de  2**0                  CONTENTS, ALLOC, LOAD, READONLY, DATA, DEBUGGING  2 .bss          01000000  00000000  00000000  00000000  2**3                  ALLOC  3 .text         00000007  00000000  00000000  0000015c  2**4                  CONTENTS, ALLOC, LOAD, READONLY, CODE
Note that in the MSVC case, the .bss section is not actually present in the executable - I imagine it is merged with the .data section. Nontheless, this means that the data section contains both initialised and non- (zero-)initialised items.

This topic is closed to new replies.

Advertisement