views:

680

answers:

2

In C/C++ we can store variables, functions, member functions, instances of a class either on a stack or a heap.

How is each implemented? How is it managed (high level)? Does gcc preallocates a chunk of memory to be used for the stack and heap, and then doles out on request? Is original memory coming from RAM?

Can a function be allocated on the heap instead of a stack?

Clarification

I am really asking about implementation and management of heap and stack memories. After reading referenced question, I didn't find anything that addresses that... thanks for the link

+1  A: 

Basically the heap is not implemented by the compiler, but instead by the C runtime library. Obviously this code is very platform dependent. On Unix or Unix-like systems the implementation is generally based on the sbrk/brk system call and a bigger amount of memory is allocated to reduce the number of system calls. This memory is then managed by the heap memory manager. If more memory is required a new call to sbrk is is issued. The current end address of the heap can be obtained with sbrk(0) if you are interested in debugging the heap management routines. Most memory managers to do not return memory to the OS during the lifetime of a process (gnu c runtime library does if certain constraints are met).

A more detailed description is available in http://gee.cs.oswego.edu/dl/html/malloc.html.

steve
This is not always the case. On OSes that are capable enough, the CRT doesn't have to. Similar with the stack: if the OS is capable enough, the compiler doesn't have to do as much. The case that the OS can handle the stack but not the heap is common but not universal.
MSalters
+1  A: 

Modern operating systems do not give you direct access to hardware RAM and instead abstract it in so called virtual memory, which it maps to RAM on demand. Each process is usually given its own private copy of the complete address space. This allows the OS to move a process' memory around in RAM at runtime or even swap it out to disk. This happens transparently, i.e. a process is not notified of such a relocation and needs not have code to handle this. (Some real time applications might use techniques to prevent having its memory swapped out).

When linking object files to an executable or a dynamic library, the linker statically allocates memory for the cpu instructions of a function/method and for all global variables. When the os loads the executable or dynamic library, it maps this pre-allocated memory into real memory.

On startup, each thread receives a private memory area called the stack. Each time you call a function/method, the compiler inserts code to automatically allocate (by incrementing the stack pointer) enough memory from the stack to hold all parameters, local variables and the return value (if any) the function/method uses. If the compiler determines that it is sufficient to leave some variables in processor registers, it does not allocate memory on the stack for it. When the function/method returns, it runs code generated by the compiler to free (by decrementing the stack pointer) this memory. Note that the destructors of any objects on the stack will be called when the block they are defined in exits, which might be a long time before returning. Also, the compiler is free to reuse the alloacated memory as it sees fit.

When an exception is thrown, the compiler compiler inserts special code that knows the layout of the stack and that can unwind it until finding a suitable exception handler.

As opposed to this, memory on the heap is allocated using new / delete, for which the compiler inserts code to request or release memory using a system library.

Please note that this is a simplified description to give you an idea of how memory allocation works.

Tobias