Sign in to follow this  
DjMaSh

Stack and Heap

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by bakery2k1
True, but I wish they wouldn't.

I couldn't agree more.

Quote:
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. Nonetheless, this means that the data section contains both initialised and non- (zero-)initialised items.

Of course, this is what I meant by 'most compilers don't produce a BSS section'. After all, it is entirely redundant in the final build. Once the linker has thrown all the uninitialised storage together into a lump, it can freely place this on the end of the existing .xdata sections, as you describe. This is why PE sections have both a virtual size and a raw size field in the PE header: If the VSize is 16MB bigger than the RawSize, 16MB of zero-initialised (though still officially uninitialised) memory will be allocated in the appropriate place. Sorry if I'm paraphrasing you. I just mean to say that I've never seen a PE (and I've debugged many) with anything but zero in the SizeOfUninitializedData field - it is always subsumed into the SizeOfInitialisedData. Similarly, I haven't encountered an explicit BSS section in a release or debug build of any PE.

Interestingly, nobody seems to know what BSS stands for. I've seen both 'Block Started by Symbol', 'Block Started Symbol' and 'Block Storage Start'.

By the way, did you imply that the GCC compiled executable did contain a BSS section?

Regards
Admiral

Share this post


Link to post
Share on other sites
Quote:
Original post by TheAdmiral
Interestingly, nobody seems to know what BSS stands for. I've seen both 'Block Started by Symbol', 'Block Started Symbol' and 'Block Storage Start'.


I've also seen "below stack segment" but I believe "Block Started by Symbol" to be generally correct. Not that that means anything any more.

Quote:
By the way, did you imply that the GCC compiled executable did contain a BSS section?


Yes. Here is the section table for the executable created from the above simple source file with GCC:
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000894 00401000 00401000 00000400 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA
1 .data 00000050 00402000 00402000 00000e00 2**4
CONTENTS, ALLOC, LOAD, DATA
2 .rdata 000000c0 00403000 00403000 00001000 2**4
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .bss 010000d0 00404000 00404000 00000000 2**4
ALLOC
4 .idata 0000027c 01405000 01405000 00001200 2**2
CONTENTS, ALLOC, LOAD, DATA
5 .stab 00013bf0 01406000 01406000 00001600 2**2
CONTENTS, READONLY, DEBUGGING, EXCLUDE
6 .stabstr 000732ff 0141a000 0141a000 00015200 2**0
CONTENTS, READONLY, DEBUGGING, EXCLUDE
GCC uses a separate .bss section rather than tacking the uninitialized data onto the end of the .data section.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this