views:

20364

answers:

13

Programming language books usually explain that value types are created on the stack, and reference types created on the heap, without really explaining what these two things are. With my only programming experience being in high level languages, I haven't read a clear explanation of this. I mean I understand what a stack is, but where and what are they relative the to the physical memory of a real computer?

  • To what extent are they controlled by the OS or language runtime?
  • What is their scope?
  • What determines the size of each of them?
  • What makes one faster?
+89  A: 

Stack:

  • Stored in computer RAM like the heap.
  • Variables created on the stack will go out of scope and automatically deallocate.
  • Much faster to allocate in comparison to variables on the heap.
  • Implemented with an actual stack data structure.
  • Stores local data, return addresses, used for parameter passing
  • Can have a stack overflow when too much of the stack is used. (mostly from inifinite (or too much) recursion, very large allocations)
  • Data created on the stack can be used without pointers.
  • You would use the stack if you know exactly how much data you need to allocate before compile time and it is not too big.
  • Usually has a maximum size already determined when your program starts

Heap:

  • Stored in computer RAM like the stack.
  • Variables on the heap must be destroyed manually and never fall out of scope. The data is freed with delete, delete[] or free
  • Slower to allocate in comparison to variables on the stack.
  • Used on demand to allocate a block of data for use by the program.
  • Can have fragmentation when there are a lot of allocations and deallocations
  • In C++ data created on the heap will be pointed to by pointers and allocated with new or malloc
  • Can have allocation failures if too big of a buffer is requested to be allocated.
  • You would use the heap if you don't know exactly how much data you will need at runtime or if you need to allocate a lot of data.
  • Responsible for memory leaks

Example:

int foo()
{

  char *pBuffer; //<--nothing allocated yet
  bool b = true;
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
Brian R. Bondy
The pointer pBuffer and the value of b are located on the stack, and are mostly likely allocated at the entrance to the function. Depending on the compiler, buffer may be allocated at the function entrance, as well.
Andy
It is a common misconception that the `C` language, as defined by the `C99` language standard (available at http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf ), requires a "stack". In fact, the word 'stack' does not even appear in the standard. This answers statements wrt/ to `C`'s stack usage are true in general, but is in no way required by the language. See http://www.knosof.co.uk/cbook/cbook.html for more info, and in particular how `C` is implemented on odd-ball architectures such as http://en.wikipedia.org/wiki/Burroughs_large_systems
johne
@Brian You should explain *why* buffer[] and the pBuffer pointer are created on the stack and why pBuffer's data is created on the heap. I think some ppl might be confused by your answer as they might think the program is specifically instructing that memory be allocated on the stack vs heap but this is not the case. Is it because Buffer is a value type whereas pBuffer is a reference type?
Howiecamp
1. There is s very fundamental aspect missing here - the different scope/lifetime of memory allocated, which affects what it can or cannot be used for.2. "Variables on the heap must be destroyed manually..." - this is not true in general but rather a specific characteristic of C/C++ (and some other languages). It is not true for garbage collected languages (e.g. .NET languages, Java) and there are also constructs that can handle the lifetime management of objects for you in C++ (e.g. reference counting) so that you don't have to manually free memory.
Hershi
@Hershi: Re 1. That is already covered by: Variables created on the stack will go out of scope and automatically deallocate. Re 2. That is already covered by: Variables on the heap must be destroyed manually and never fall out of scope. The data is freed with delete, delete[] or free
Brian R. Bondy
@BrianI'm a newbie and I have a question on this topic. If i declare a variable in a certain way, is it either on the stack or on the heap? There's no other place a declared variable is residing?What about static members?
kobac
+1  A: 

The wikipedia articles mentioned by "Scott S" refer to different uses of the terms "heap" and "stack" that do not refer to the question. Better Wikipedia articles:

http://en.wikipedia.org/wiki/Stack-based_memory_allocation

http://en.wikipedia.org/wiki/Dynamic_memory_allocation

+14  A: 

The Stack When you call a function the arguments to that function plus some other overhead is put on the stack. Some info (such as where to go on return) is also stored there. When you declare a variable inside your function, that variable is also allocated on the stack.

Deallocating the stack is pretty simple because you always deallocate in the reverse order in which you allocate. Stack stuff is added as you enter functions, the corresponding data is removed as you exit them. This means that you tend to stay within a small region of the stack unless you call lots of functions that call lots of other functions (or create a recursive solution).

The Heap The heap is a generic name for where you put the data that you create on the fly. If you don't know how many spaceships your program is going to create, you are likely to use the new (or malloc or equivalent) operator to create each spaceship. This allocation is going to stick around for a while, so it is likely we will free things in a different order than we created them.

Thus, the heap is far more complex, because there end up being regions of memory that are unused interleaved with chunks that are - memory gets fragmented. Finding free memory of the size you need is a difficult problem. This is why the heap should be avoided (though it is still often used).

Implementation Implementation of both the stack and heap is usually down to the runtime / OS. Often games and other applications that are performance critical create their own memory solutions that grab a large chunk of memory from the heap and then dish it out internally to avoid relying on the OS for memory.

This is only practical if your memory usage is quite different from the norm - i.e for games where you load a level in one huge operation and can chuck the whole lot away in another huge operation.

Physical location in memory This is less relevant than you think because of a technology called Virtual Memory which makes your program think that you have access to a certain address where the physical data is somewhere else (even on the hard disc!). The addresses you get for the stack are in increasing order as your call tree gets deeper. The addresses for the heap are un-predictable (i.e implimentation specific) and frankly not important.

Tom Leys
A recommendation to avoid using the heap is pretty strong. Modern systems have good heap managers, and modern dynamic languages use the heap extensively (without the programmer really worrying about it). I'd say use the heap, but with a manual allocator, don't forget to free!
Greg Hewgill
If you can use the stack or the heap, use the stack. If you can't use the stack, really no choice. I use both a lot, and of course using std::vector or similar hits the heap. For a novice, you avoid the heap because the stack is simply so easy!!
Tom Leys
+7  A: 

The stack is a portion of memory that can be manipulated via several key assembly language instructions, such as 'pop' (remove and return a value from the stack) and 'push' (push a value to the stack), but also call (call a subroutine - this pushes the address to return to the stack) and return (return from a subroutine - this pops the address off of the stack and jumps to it). It's the region of memory below the stack pointer register, which can be set as needed. The stack is also used for passing arguments to subroutines, and also for preserving the values in registers before calling subroutines.

The heap is a portion of memory that is given to an application by the operating system, typically through a syscall like malloc. On modern OSes this memory is a set of pages that only the calling process has access to.

The size of the stack is determined at runtime, and generally does not grow after the program launches. In a C program, the stack needs to be large enough to hold every variable declared within each function. The heap will grow dynamically as needed, but the OS is ultimately making the call (it will often grow the heap by more than the value requested by malloc, so that at least some future mallocs won't need to go back to the kernel to get more memory. This behavior is often customizable)

Because you've allocated the stack before launching the program, you never need to malloc before you can use the stack, so that's a slight advantage there. In practice, it's very hard to predict what will be fast and what will be slow in modern operating systems that have virtual memory subsystems, because how the pages are implemented and where they are stored is an implementation detail.

Daniel Papasian
Also worth mentioning here that intel heavily optimizes stack accesses, especially things such as predicting where you return from a function.
Tom Leys
+7  A: 

Others have answered the broad strokes pretty well, so I'll throw in a few details.

  1. Stack and heap need not be singular. A common situation in which you have more than one stack is if you have more than one thread in a process. In this case each thread has its own stack. You can also have more than one heap, for example some DLL configurations can result in different DLLs allocating from different heaps, which is why it's generally a bad idea to release memory allocated by a different library.

  2. In C you can get the benefit of variable length allocation through the use of alloca, which allocates on the stack, as opposed to alloc, which allocates on the heap. This memory won't survive your return statement, but it's useful for a scratch buffer.

  3. On windows making a huge temporary buffer that you don't use much of is not free. This is because the compiler will generate a stack probe loop that is called every time your function is entered to make sure the stack exists (because windows uses a single guard page at the end of your stack to detect when it needs to grow the stack, if you access memory more than one page off the end of the stack you will crash). Example:

    void myfunction()
    {
       char big[10000000];
       // do something that only uses for first 1K of big 99% of the time.
    }
Don Neufeld
+78  A: 

The stack is the memory set aside as scratch space for a thread of execution. When a function is called, a block is reserved on the top of the stack for local variables and some bookeeping data. When that function returns, the block becomes unused and can be used the next time a function is called. The stack is always reserved in a LIFO order; the most recently reserved block is always the next block to be freed. This makes it really simple to keep track of the stack; freeing a block from the stack is nothing more than adjusting one pointer.

The heap is memory set aside for dynamic allocation. Unlike the stack, there's no enforced pattern to the allocation and deallocation of blocks from the heap; you can allocate a block at any time and free it at any time. This makes it much more complex to keep track of which parts of the heap are allocated or free at any given time; there are many custom heap allocators available to tune heap performance for different usage patterns.

Each thread gets a stack, while there's typically only one heap for the application (although it isn't uncommon to have multiple heaps for different types of allocation).

To answer your questions directly:

  • The OS allocates the stack for each system-level thread when the thread is created. Typically the OS is called by the language runtime to allocate the heap for the application.

  • The stack is attached to a thread, so when the thread exits the stack is reclaimed. The heap is typically allocated at application startup by the runtime, and is reclaimed when the application (technically process) exits.

  • The size of the stack is set when a thread is created. The size of the heap is set on application startup, but can grow as space is needed (the allocator requests more memory from the operating system).

  • The stack is faster because the access pattern makes it trivial to allocate memory from it, while the heap has much more complex bookkeeping involved in an allocation or free. Also, each byte in the stack tends to be reused very frequently which means it tends to be mapped to the processor's cache, making it very fast.

Jeff Hill
I think you should clarify your last statement. According to your reasoning, ONLY allocation is necessarily faster, right?
Joe Philllips
To add to my previous statement, if you're going to allocate an object once and keep it throughout the life of your process, it would be better to use a heap, right?
Joe Philllips
I think this image will help to understand this subject: http://vikashazrati.files.wordpress.com/2007/10/stacknheap.png
uzay95
@Jeff Hill Please define "dynamim allocation".
Howiecamp
@uzay95 link to that article: http://vikashazrati.wordpress.com/2007/10/01/quicktip-java-basics-stack-and-heap/
instantsetsuna
+3  A: 

I think many other people have given you mostly correct answers on this matter.

One detail that has been missed, however, is that the "heap" should in fact probably be called the "free store". The reason for this distinction is that the original free store was implemented with a data structure known as a "binomial heap." For that reason, allocating from early implementations of malloc()/free() was allocation from a heap. However, in this modern day, most free stores are implemented with very elaborate data structures that are not binomial heaps.

Another nitpick- most of the answers (lightly) imply that the use of a "stack" is required by the `C` language. This is a common misconception, though it is the (by far) dominate paradigm for implementing `C99 6.2.4 automatic storage duration objects` (variables). In fact, the word "stack" does not even appear in the `C99` language standard: http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
johne
+6  A: 

Others have directly answered your question, but when trying to understand the stack and the heap, I think it is helpful to consider the memory layout of a traditional UNIX process (without threads and mmap()-based allocators). The Memory Management Glossary web page has a diagram of this memory layout.

The stack and heap are traditionally located at opposite ends of the process's virtual address space. The stack grows automatically when accessed, up to a size set by the kernel (which can be adjusted with setrlimit(RLIMIT_STACK, ...)). The heap grows when the memory allocator invokes the brk() or sbrk() system call, mapping more pages of physical memory into the process's virtual address space.

In systems without virtual memory, such as some embedded systems, the same basic layout often applies, except the stack and heap are fixed in size. However, in other embedded systems (such as those based on Microchip PIC microcontrollers), the program stack is a separate block of memory that is not addressable by data movement instructions, and can only be modified or read indirectly through program flow instructions (call, return, etc.). Other architectures, such as Intel Itanium processors, have multiple stacks. In this sense, the stack is an element of the CPU architecture.

bk1e
+54  A: 
thomasrutter
+1 for the visual representation. I wish all programming concepts were taught in this manner.
Evan Plaice
+1 You listen to words "stack" and "heap" so many times that you forget their literal meaning. :-)
ydobonmai
+3  A: 

Simply, the stack is where local variables get created. Also, every time you call a subroutine the program counter (pointer to the next machine instruction) and any important registers, and sometimes the parameters get pushed on the stack. Then any local variables inside the subroutine are pushed onto the stack (and used from there). When the subroutine finishes, that stuff all gets popped back off the stack. The PC and register data gets and put back where it was as it is popped, so your program can go on its merry way.

The heap is the area of memory dynamic memory allocations are made out of (explicit "new" or "allocate" calls). It is a special data structure that can keep track of blocks of memory of varying sizes and their allocation status.

In "classic" systems RAM was laid out such that the stack pointer started out at the bottom of memory, the heap pointer started out at the top, and they grew towards each other. If they overlap, you are out of RAM. That doesn't work with modern multi-threaded OSes though. Every thread has to have its own stack, and those can get created dynamicly.

T.E.D.
+2  A: 

You can do some interesting things with the stack. For instance, you have functions like alloca (assuming you can get past the copious warnings concerning its use), which is a form of malloc that specifically uses the stack, not the heap, for memory.

That said, stack-based memory errors are some of the worst I've experienced. If you use heap memory, and you overstep the bounds of your allocated block, you have a decent chance of triggering a segment fault. (Not 100%: your block may be incidentally contiguous with another that you have previously allocated.) But since variables created on the stack are always contiguous with each other, writing out of bounds can change the value of another variable. I have learned that whenever I feel that my program has stopped obeying the laws of logic, it is probably buffer overflow.

Peter
+2  A: 

From WikiAnwser.

Stack

When a function or a method calls another function which in turns calls another function etc., the execution of all those functions remains suspended until the very last function returns its value.

This chain of suspended function calls is the stack, because elements in the stack (function calls) depend on each other.

The stack is important to consider in exception handling and thread executions.

Heap

The heap is simply the memory used by programs to store variables. Element of the heap (variables) have no dependencies with each other and can always be accessed randomly at any time.

I like the accepted answer better since it's even more low level.

Chenster
+12  A: 

(I have moved this answer from another question that was more or less a dupe of this.)

The answer to your question is implementation specific and may be vary across compilers and processor architectures. However, here is a simplified explanation.

  • Both the stack and the heap are memory areas allocated from the underlying operating system (often virtual memory that are mapped to physical memory on demand).
  • In a multi-threaded environment each thread will have it's own completely independent stack but they will share the heap. Concurrent access has to be controlled on the heap and is not possible on the stack.

The heap

  • The heap contains a linked list of used and free blocks. New allocations on the heap (by new or malloc) are satisfied by creating a suitable block from one of the free blocks. This requires updating list of blocks on the heap. This meta information about the blocks on the heap is also stored on the heap often in a small area just in front of every block.
  • As the heap grows new blocks are often allocated from lower addresses towards higher addresses. Thus you can think of the heap as a heap of memory blocks that grows in size as memory is allocated. If the heap is too small for an allocation the size can often be increased by acquiring more memory from the underlying operating system.

The stack

  • The stack often works in close tandem with a special register on the CPU named the stack pointer. Initially the stack pointer points to the top of the stack (the highest address on the stack).
  • The CPU has special instructions for pushing values onto the stack and poping them back from the stack. Each push will store the value at the current location of the stack pointer and decrease the stack pointer. A pop will increase the stack pointer and retrieve the value pointed to by the stack pointer. The values stored and retrieved are the values of the CPU registers.
  • When a function is called the CPU uses special instructions that pushes the current instruction pointer, i.e. the address of the code executing on the stack. The CPU then jumps to the function by setting the instruction pointer to the address of the function called. Later, when the function returns the old instruction pointer is poped from the stack and execution resumes at the code just after the call to the function.
  • When a function is entered the stack pointer is decreased to allocate more space on the stack for local (automatic) variables. If the function has one local 32 bit variable four bytes are set aside on the stack. When the function returns the stack pointer is moved back to free the allocated area.
  • If a function has parameters these are pushed onto the stack before the call to the function. The code in the function is then able to navigate up the stack from the current stack pointer to locate these values.
  • Nesting function calls works like a charm. Each new call will allocate function parameters, the return address and space for local variables and these activation records can be stacked for nested calls and will unwind in the correct way when the functions return.
  • As the stack is a limited block of memory you can cause a stack overflow by calling too many nested functions and/or allocating too much space for local variables. Often the memory area used for the stack is set up in such a way that writing below the bottom (the lowest address) of the stack will trigger a trap or exception in the CPU. This exceptional condition can then be caught by the runtime and converted into some kind of stack overflow exception.

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

No, activation records for functions (i.e. local or automatic variables) are allocated on the stack that is used not only to store these variables, but also keep track of nested function calls.

How the heap is managed is really up to the run-time environment. C uses malloc and C++ uses new, but many other languages have garbage collection.

However, the stack is more low level feature closely tied to the processor architecture. Growing the heap when there is not enough space isn't too hard since it can be implemented in the library call that handles the heap. However, growing the stack is often impossible as the stack overflow only is discovered when it is too late and shutting down the thread of execution is the only viable option.

Martin Liversage
+1 for the info reg. meta information stored at the start of each block/chunk of memory allocated dynamically via malloc/new
aks