7.9 — The stack and the heap

The memory a program uses is typically divided into a few different areas, called segments:

  • The code segment (also called a text segment), where the compiled program sits in memory. The code segment is typically read-only.
  • The bss segment (also called the uninitialized data segment), where zero-initialized global and static variables are stored.
  • The data segment (also called the initialized data segment), where initialized global and static variables are stored.
  • The heap, where dynamically allocated variables are allocated from.
  • The call stack, where function parameters, local variables, and other function-related information are stored.

For this lesson, we’ll focus primarily on the heap and the stack, as that is where most of the interesting stuff takes place.

The heap segment

The heap segment (also known as the “free store”) keeps track of memory used for dynamic memory allocation. We talked about the heap a bit already in lesson 6.9 -- Dynamic memory allocation with new and delete, so this will be a recap.

In C++, when you use the new operator to allocate memory, this memory is allocated in the application’s heap segment.

The address of this memory is passed back by operator new, and can then be stored in a pointer. You do not have to worry about the mechanics behind the process of how free memory is located and allocated to the user. However, it is worth knowing that sequential memory requests may not result in sequential memory addresses being allocated!

When a dynamically allocated variable is deleted, the memory is “returned” to the heap and can then be reassigned as future allocation requests are received. Remember that deleting a pointer does not delete the variable, it just returns the memory at the associated address back to the operating system.

The heap has advantages and disadvantages:

  • Allocating memory on the heap is comparatively slow.
  • Allocated memory stays allocated until it is specifically deallocated (beware memory leaks) or the application ends (at which point the OS should clean it up).
  • Dynamically allocated memory must be accessed through a pointer. Dereferencing a pointer is slower than accessing a variable directly.
  • Because the heap is a big pool of memory, large arrays, structures, or classes can be allocated here.

The call stack

The call stack (usually referred to as “the stack”) has a much more interesting role to play. The call stack keeps track of all the active functions (those that have been called but have not yet terminated) from the start of the program to the current point of execution, and handles allocation of all function parameters and local variables.

The call stack is implemented as a stack data structure. So before we can talk about how the call stack works, we need to understand what a stack data structure is.

The stack data structure

A data structure is a programming mechanism for organizing data so that it can be used efficiently. You’ve already seen several types of data structures, such as arrays and structs. Both of these data structures provide mechanisms for storing data and accessing that data in an efficient way. There are many additional data structures that are commonly used in programming, quite a few of which are implemented in the standard library, and a stack is one of those.

Consider a stack of plates in a cafeteria. Because each plate is heavy and they are stacked, you can really only do one of three things:
1) Look at the surface of the top plate
2) Take the top plate off the stack (exposing the one underneath, if it exists)
3) Put a new plate on top of the stack (hiding the one underneath, if it exists)

In computer programming, a stack is a container data structure that holds multiple variables (much like an array). However, whereas an array lets you access and modify elements in any order you wish (called random access), a stack is more limited. The operations that can be performed on a stack correspond to the three things mentioned above:

1) Look at the top item on the stack (usually done via a function called top(), but sometimes called peek())
2) Take the top item off of the stack (done via a function called pop())
3) Put a new item on top of the stack (done via a function called push())

A stack is a last-in, first-out (LIFO) structure. The last item pushed onto the stack will be the first item popped off. If you put a new plate on top of the stack, the first plate removed from the stack will be the plate you just pushed on last. Last on, first off. As items are pushed onto a stack, the stack grows larger -- as items are popped off, the stack grows smaller.

For example, here’s a short sequence showing how pushing and popping on a stack works:

Stack: empty
Push 1
Stack: 1
Push 2
Stack: 1 2
Push 3
Stack: 1 2 3
Stack: 1 2
Stack: 1

The plate analogy is a pretty good analogy as to how the call stack works, but we can make a better analogy. Consider a bunch of mailboxes, all stacked on top of each other. Each mailbox can only hold one item, and all mailboxes start out empty. Furthermore, each mailbox is nailed to the mailbox below it, so the number of mailboxes can not be changed. If we can’t change the number of mailboxes, how do we get a stack-like behavior?

First, we use a marker (like a post-it note) to keep track of where the bottom-most empty mailbox is. In the beginning, this will be the lowest mailbox. When we push an item onto our mailbox stack, we put it in the mailbox that is marked (which is the first empty mailbox), and move the marker up one mailbox. When we pop an item off the stack, we move the marker down one mailbox and remove the item from that mailbox. Anything below the marker is considered “on the stack”. Anything at the marker or above the marker is not on the stack.

The call stack segment

The call stack segment holds the memory used for the call stack. When the application starts, the main() function is pushed on the call stack by the operating system. Then the program begins executing.

When a function call is encountered, the function is pushed onto the call stack. When the current function ends, that function is popped off the call stack. Thus, by looking at the functions pushed on the call stack, we can see all of the functions that were called to get to the current point of execution.

Our mailbox analogy above is fairly analogous to how the call stack works. The call stack is a fixed-size chunk of memory addresses. The mailboxes are memory addresses, and the “items” we’re pushing and popping on the stack are called stack frames. A stack frame keeps track of all of the data associated with one function call. We’ll talk more about stack frames in a bit. The “marker” is a register (a small piece of memory in the CPU) known as the stack pointer (sometimes abbreviated “SP”). The stack pointer keeps track of where the top of the call stack currently is.

The only difference between our hypothetical mailbox stack and the call stack is that when we pop an item off the call stack, we don’t have to erase the memory (the equivalent of emptying the mailbox). We can just leave it to be overwritten by the next item pushed to that piece of memory. Because the stack pointer will be below that memory location, we know that memory location is not on the stack.

The call stack in action

Let’s examine in more detail how the call stack works. Here is the sequence of steps that takes place when a function is called:

  1. The program encounters a function call.
  2. A stack frame is constructed and pushed on the stack. The stack frame consists of:
    • The address of the instruction beyond the function call (called the return address). This is how the CPU remembers where to return to after the called function exits.
    • All function arguments.
    • Memory for any local variables.
    • Saved copies of any registers modified by the function that need to be restored when the function returns
  3. The CPU jumps to the function’s start point.
  4. The instructions inside of the function begin executing.

When the function terminates, the following steps happen:

  1. Registers are restored from the call stack
  2. The stack frame is popped off the stack. This frees the memory for all local variables and arguments.
  3. The return value is handled.
  4. The CPU resumes execution at the return address.

Return values can be handled in a number of different ways, depending on the computer’s architecture. Some architectures include the return value as part of the stack frame. Others use CPU registers.

Typically, it is not important to know all the details about how the call stack works. However, understanding that functions are effectively pushed on the stack when they are called and popped off when they return gives you the fundamentals needed to understand recursion, as well as some other concepts that are useful when debugging.

A quick and dirty call stack example

Consider the following simple application:

The call stack looks like the following at the labeled points:




foo() (including parameter x)



Stack overflow

The stack has a limited size, and consequently can only hold a limited amount of information. On Windows, the default stack size is 1MB. On some unix machines, it can be as large as 8MB. If the program tries to put too much information on the stack, stack overflow will result. Stack overflow happens when all the memory in the stack has been allocated -- in that case, further allocations begin overflowing into other sections of memory.

Stack overflow is generally the result of allocating too many variables on the stack, and/or making too many nested function calls (where function A calls function B calls function C calls function D etc…) Overflowing the stack will generally cause a program to crash.

Here is an example program that will likely cause a stack overflow. You can run it on your system and watch it crash:

This program tries to allocate a huge array on the stack. Because the stack is not large enough to handle this array, the array allocation overflows into portions of memory the program is not allowed to use. Consequently, the program crashes.

Here’s another program that will cause a stack overflow for a different reason:

In the above program, a stack frame is pushed on the stack every time function foo() is called. Since foo() calls itself infinitely, eventually the stack will run out of memory and cause an overflow.

The stack has advantages and disadvantages:

  • Allocating memory on the stack is comparatively fast.
  • Memory allocated on the stack stays in scope as long as it is on the stack. It is destroyed when it is popped off the stack.
  • All memory allocated on the stack is known at compile time. Consequently, this memory can be accessed directly through a variable.
  • Because the stack is relatively small, it is generally not a good idea to do anything that eats up lots of stack space. This includes passing by value or creating local variables of large arrays or other memory-intensive structures.
7.10 -- std::vector capacity and stack behavior
7.8 -- Function Pointers

135 comments to 7.9 — The stack and the heap

  • Amr

    Hello alex ,
    First i want to thank you for this tutorial, but i deployed a multithreaded program which when allocate all memory on the stack use arrays instead of vectors for example
    func x(some parameters){
    vector  <double >a;
    vector <double> e;
    vector <double> c;
    vector  <bool> d;
    vector <bool> x;
    for( int i =0 ; i <100000 ; i++ )
    for (int j =0 ; j <100000; j++ )
    double inphase[4];
    double quadrature[4];
    bool status [4];
    bool hidden [4];
    here some reading and writng in those arrays and vectors

    program executes well but one transforming the vecyors to arrays program becomes 10x slower how is that and when switching array with vectors and vectors wth arrays program executes fast again , i am using open mp and visual studio 2010 by the way the parallization is for this function each thread call this function seperately.

    • Alex

      I’m not sure. In general, std::array should be faster than std::vector (at the cost of being less flexible). You must be accruing some kind of inefficiency with std::array or stack allocation, perhaps because multiple threads don’t share a stack.

  • AlexR


    That was an interesting read. I had a random idea popped in my head that might sound dumb. I understand the difference between the stack and the heap (I think) but I wonder is it possible to use a pointer to point to another stack instead of grab memory from the heap? Instead of calling a function and pushing onto the main stack, I was thinking maybe the pointer can allocate the function call to another stack and then you could push additional functions onto that.

    I guess the only thing that might be wrong there is that the OS will terminate the program for trying to access memory it wasn’t given. Is that right?

    I’m not sure if I explained that clearly but in my mind I imagine something like:

    • Alex

      A program is only set up with one stack, and the compiler is set up to automatically use it. So when you call a function, it goes on the main stack. I’m not aware of any way to reroute to a second stack.

  • Eno

    Dear Alex,
    I have a module and I want to save it in a persistent memory in order not to be lost or crashed when I call it again starting from the point where I left it, and I found the only way to do that is to transfer it to a disk after saving it in a file using mmap command, but the problem is I found this command can not be executed under Windows OS because it’s included in <sys/mman.h> which is one of the Linux header files. So is there an alternative command can be executed under Windows platform using vc++.


    • Alex

      I can’t really speak to this, as it’s OS specific and not in my core area of knowledge. Google search or Stack Overflow is probably your best bet here.

  • Eno

    Dear Alex,

    I couldn’t because each project has its header files and main function! so how can I merge these two projects together in one project. Actually, I’m looking for steps to do that.


  • Hi Alex,
    Thanks for the very detailed guide. Very easy to understand for someone who’s not a CS major.

  • Eno

    Dear Alex,
    I have my own project written in visual c++ language (2015 enterprise copy).I want to add a tidy interface for the user. I created another project using windows form as an interface for my code and its running, but the problem with me I can’t combine my project (including a header file+main.cpp + many .cpp files) with the interface which I created for them. How can I connect two projects (c++ code+Interface)? Any help would be much appreciated.

    • Alex

      Generally you’ll want to put your interface and your code in the same project. What’s preventing you with putting your code files from the first project into the interface project?

  • Jonathan

    So if the stack is so fast, why don’t we use a bigger stack and put all memory on the stack?

    • Alex

      Stack memory must be contiguous, so it essentially has to be reserved ahead of time. That means all of the memory your application uses for the stack is assigned to your application’s use only. If you made the stack huge, then your application would reserve all of your memory for its own use, and your system would quickly run out of memory.

      Heap memory is useful because it doesn’t need to be allocated contiguously, so it can be much more easily shared amongst all the running applications.

      For what it’s worth, most compilers have a way to increase the stack size for your application if that’s desirable for your use case.

  • Eno

    Dear Alex,

    Many Many thanks for your help. Finally, I got rid of the error by using void pointer which was your suggestion. I’m really excited now. Once
    again thank you so much.

    Note// I couldn’t find your email in the website.

    Kind regards.

  • Eno

    Dear Alex,
    Many thanks for clarifying. So according to what did you mention above and also because I’m still getting that error, I switched my code to c language. As far as I know c++ is OOP and support for classes,..etc. My question is:
    I’m using visual studio 2015 enterprise and what I did is just convert my original code which was written in c++ to c and compiled as (c code (/TC)) and I can’t see any red lines under my code but when I compile it there are 3077 errors!
    Note //
    I compiled my code as a project including (a header file, many .cpp files and main.cpp).Is that ok?  

    Best wishes.

    • Alex

      Compiling your code as a project file containing a header and many .cpp files is fine. I’m not sure why you are trying to compile it as C code. C++ is more than just C plus OOP.

      • Eno

        Dear Alex,
        I’m doing that in order to rid of that error. I’m thinking maybe c code compiler will help me in this case.Once again, error of assigning address of two functions with different signatures to a variable defined as unsigned Int is something unreasonable because I want their address in memory to be assigned into variable not the content! If  c or c++ compiler couldn’t deal with this kind of error, In my opinion, this is a big compiler bug.

        Many thanks.

        • Alex

          The inability to mismatch a pointer variable with the object being pointed to is not a bug -- it’s part of C++’s strong type checking system. For the same reason you can’t have a double pointer point at an integer value, you can’t have a function pointer for a function with a particular signature point to a function that has a different signature.

          As I noted above, you can kind of work around this by using void pointers, which can point to anything.

  • Eno

    Dear Alex,

    I got an error and I think that error is something unreasonable. The error is (C2440’=’: cannot convert from ‘void (__cdecl *)(float)’ to ‘u32′)

    I have two functions:-

    double x(void)      // Function 1                      
      return double;
    void y(double )     // Function 2
    In the .h file I have :

    typedef  double(*u32)();

    struct mc
        u32 add;
    In the .cpp file:

    mc *ptr=new mc[3];;  

        xptr = x;
        ptr->add = xptr;      

        yptr = y;
        ptr->add = yptr;                 <--  // The Error is here (C2440’=’: cannot convert from ‘void (__cdecl *)(float)’ to ‘u32’)

    I want to assign the address of above functions into (add) variable, Its working for the first function x but not working for function y! I know because its mathing the definition of function x but not y? so why should be like that?  I’m very confused
    because I’m dealing with the address of the function not with the type of the function (i.e. I want to assign the function address in the memory into a variable (add) of type unsigned int within the array of struct data type. I’m looking for a common definition works for all type of function (doesn’t matter what’s the parameters or the return vales of the functions).

    Best regards.

    • Alex

      You’re getting an error because you’re trying to assign a function with signature void(*)(double) to a variable with signature double(*)(). C++’s strong typing is preventing this.

      > I’m looking for a common definition works for all type of function (doesn’t matter what’s the parameters or the return vales of the functions).

      There isn’t an easy way to do this due to the strong typing rules. Closest thing you can do is use a void pointer, which will allow you to assign any kind of function pointer to it. But then the problem is how you interpret the void pointer into something meaningful that you can call. One way would be to add another member to struct mc to keep track of what type of function pointer your void pointer is, so you can cast it back to a function pointer in order to call it.

  • Eno

    Dear Alex,
    Many thanks for reply and assistance. My question was exactly how to compile a piece of code into any program that needs that functionality  (i.e some thing like a master key which opens all the doors)?

    Secondly, In the program below, I need to assign a function address (in the example below fu()) by using the function pointer to a field defined within a struct data type (in the example below (add) of type unsigned int), but I get the error (different type modifiers).  


    typedef  unsigned int(*u32)();

    typedef struct {
         u32 add;

    double fu()   ;   this function might return double or struct
    { cout << "Hi"
      return 0;

    Is it posible to assign any function address to a variable of type unsigned int? how the definition should be?
    Note// I asked this question before and you thankfully answered me but the function was reurn unsigned int. Now it could be return double or struct.


    • Alex

      For your first question, separate the code you want to include in many programs into its own .cpp and .h file pair. Then just include those files in any project you want to use them in. There are other ways, but they are more complicated.

      fu() is defined to return a double, so it can’t return a struct. A function can only have one return type. And no, you can’t assign a function pointer to a variable of type unsigned int.

  • Eno

    Dear Alex,
    I’m wondering how can I make an idea to work in general way. For example, if I have a code and that code solves a particular problem and then I want to generalise that code to be worked in any situation (if tested by another program and should be working ).Could you please assist me by providing an example or even a website clarifies how achieve that? Thanks in advance.

    • Alex

      There’s no one-size-fits-all answer to this question. However, most of the time, this can be accomplished by creating a .cpp and .h file and writing a function (or functions) or a class that can be compiled into any program that needs that functionality.

      The functions or classes should:
      * Take all of the necessary inputs
      * Do whatever calculations are necessary
      * Make the answers available to the caller

      I’m not sure I have any lessons specifically on this topic, but it would be good to write one, so I’ll take a note.

  • Mike

    Hi, thanks for the tutorial.

    I have a question concerning how variables and their addresses are stored. I understand that a variable lives at an address, and that that address contains information to be interpreted depending on the variable type. My question is the following. Where does the compiler store memory addresses of variables? Is there a directory where the compiler can look up, for example the (say, initialised) variable "var1" to know what address to look up?

    Furthermore I am very interested in finding out if there is a way to assign variable names to dynamically allocated variables, from a constructed string for example? In other words, could I have code that looks like

    I’d imagine the two concepts are related?

    • Alex

      > Where does the compiler store memory addresses of variables? Is there a directory where the compiler can look up, for example the (say, initialised) variable “var1” to know what address to look up?

      When the compiler is compiling a program, it builds a table (called a symbol table) that contains all of the names, types, and addresses of the variables it has seen. The symbol table is only needed during compile time.

      There’s no way to directly assign a variable name to a dynamic address, but you can always create a pointer and point at the address.

      In your example, you can’t assign ptr to a string, because the types don’t match, and C++ will flag this as an error. There are ways to override this (via a reinterpret_cast), but generally you won’t want to, because it doesn’t make sense.

  • Eno

    Dear Alex,

    Thanks for replying. Actually, what I want to do is to call(a module or a process) through (main.cpp) and in order to achieve that I need to know the address of the module. I need that address to use it in a data structure which I’m trying to build it.

    According to what you said above (It’s not possible),so just tell me please is the address of the module (f.cpp)which includes the functions is the same as the first function(f1)? (The above example project p):

    i.e. does f.cpp has the same address to f1 in memory? if not. Is there any possibility to get the address of the module f.cpp using c++? Otherwise I will try to find another way.

    • Alex

      f.cpp does only exists for purposes of organizing your code. It does not have any address or exist in any form once you’ve compiled your program.

      If you want to call a function in f.cpp, all you need to do is either call it directly or get a function pointer to it, and call it through that. The only thing required for either of those things to happen is to ensure main.cpp knows that the functions exist in f.cpp, which you can do through forward prototypes (either directly, or by #including a header that contains them).

  • Eno

    Dear Alex,

    I’m wondering whether I can get the address of a (file.cpp) within a project or not? I need that address.

    i.e./ Suppose a (project) p has the following files:

    The file (f.cpp) has two functions within (f1 &f2)
    it’s easy to get the address of f1 or f2 using the function pointer, but I don’t know how can I get the address of (f.cpp) itself! is that possible with c++?  Any help would be appreciated.

    • Alex

      It’s not possible -- files are just used for storing code -- they have no relevance and aren’t preserved in any form inside the compiled executable. What would you even do with the address of f.cpp if you had it?

  • Eno

    Dear Alex,
    In the program below, I need to assign a function address (in the example below fu()) by using the function pointer to a field defined within a struct data type (in the example add), but I got the error below. So, what should be the definition of (add)? Thanks in advance.

    typedef  uint32_t u32;
    typedef struct {
         u32 add;

    unsigned int fu()
    { cout << "Hi"
      return 0;
    int main()
    unsigned int(*fptr)();
        fptr = fu;

        id *ptr = new id[3];
        (ptr+0)->add=fptr;  // The error in this line
        cout << (ptr + 0)->add;
    return 0;
    Error (active)    a value of type "unsigned int (*)()" cannot be assigned to an entity of type "unsigned int"

    • Alex

      Yes, you’re trying to assign a function pointer of type unsigned int(*)() to an unsigned int. That’s a type mismatch.

      Your typedef should be:

      • Eno

        Dear Alex,
        I would like to thank you for sending me the correct instruction. It’s working now and I’m really happy for that. If I have other mistakes in the future I’ll ask you again. Thanks for your patience .

  • Eno

    Dear Alex,

    Thank you so much for replying and sending me the code. I will follow them and if I found any difficulties with the language because I’m new to c++ I will message you again.

    Your help is really appreciated.

  • Eno

    I don’t know exactly what is the purpose of dynamic allocation. In my case I want to create an (array of struct), so am I need to allocate memory for that array on the heap using (new or malloc,…) or just create it directly? I’m really confused!

    • Alex

      Ah, got it. Yup, just use the new keyword to allocate your array of structs on the heap.

  • Eno

    Thx Alex. Ok let’s suppose I want to allocate memory on the heap in order to define an array within, so what should be the first step according to c++ instructions ( what instruction(s) must be used)?

    • Alex

      If you want to allocate memory on the heap, you use the new keyword. For example:

      The new keyword is the C++ equivalent of C’s malloc and calloc.

  • Eno

    Dear Alex,
    Many thx for your reply.
    I will try to clarify it a little more. I need to create an array within a special segment and that segment should not be in normal user space (i.e special design segment) and the only way to access such a segment is to use the system to do that( i.e the executing program can’t go around that segment just by asking the system to do it). Then I want to create an array in that segment to put some information. My problem is where should I keep that array? Am I need first to use instructions such as (malloc, calloc,….) in order to allocate a space for the array or there is another way to reserve part of memory (a segment ) to put the array there? I’m confused with how the start point should be (the beginning) in order to continue? I hope it’s clear now!

    • Alex

      As far as I know, C++ only allows you to allocate memory in two ways: on the stack, and on the heap (general system memory). If you want to allocate memory elsewhere, I’m not sure how you’d do it.

  • Eno

    Dear Alex,
    Many thanks for this amazing tutorial.
    However,I have a question. I have started to use C++ as a programming language. I’m trying to allocate a specific segment in a protected part within the memory and I have also store an array in that segment. So my question is am I need to allocate part of memory for that segment first? if yes,  how can I achieve that? should I use instructions such as (malloc, calloc,….) or just define the array directly? I need help! thx in advance

  • Matt

    Under section "Stack overflow", second paragraph, you wrote:
    "Overflowing the stack will generally causes a program to crash."

    “Causes” should be “cause”.

  • Jack

    The second stack overflow example doesn’t crash on my machine, using VS 2015. It just does nothing. Maybe the compiler figured out the function doesn’t do anything anyways? I think this might be the case since when I changed the code to

    void foo(int i)
    std::cout << i;

    it produced a stack overflow as expected.

  • Nyap

    Does the kernel decide the size of the stack

    • Alex

      No, the compiler does.

      • Nyap

        oh yeah i’m stupid i mean’t the heap

      • Chris

        you said OS decide the size of stack: "On Windows, the default stack size is 1MB. On some unix machines, it can be as large as 8MB.". so which one is decide that? compiler or OS?

        • Alex

          The size of the stack is part of the executable itself. The executable is managed by the OS, but created by the linker. So technically, the linker sets the initial stack size, but the OS manages it (and in some cases, will let you change it -- for example, on linux you can use the ulimit command to change the stack size for a given executable).

  • Rob G.

    All function arguments are placed on the stack.
    Local variables are pushed onto the stack.

    what is the difference between placed on the stack and pushed on the stack?

    also why is the stack memory so small ~1mb?

    • Alex

      I’m using placed and pushed interchangeably in this context.

      The stack is small because it generally doesn’t need to be larger. Having a larger stack would increase the amount of memory your program needs to run. Also because the stack needs to be in contiguous memory, that limits what memory can be used for this.

      That said, the stack size can be changed in the rare case you need something larger.

      • Rob G.

        These days you see games that are 8gb plus in size -- 32gb in RAM- so it still operates with a 1mb stack?

        • Alex

          I honestly don’t know if large commercial applications typically increase the stack size. If you do most of your large variable allocations on the heap, you shouldn’t need a large stack at all (since the stack will just contain the 4 or 8-byte pointers holding the address of the heap memory).

  • J3ANP3T3R

    in the example :




    foo() (including parameter x)


    main()   <--- does the stack store additional information as to where exactly in main() to continue ?

  • Harshul

    I think you misunderstood my problem let me put it in a more explained way to you…

    If we use an array then the elements are laid out contiguously which means what if a program is using first element then it can easily use the second element as it is just after the current element. This is how I think….

    But one friend of mine presented a totally different ideology. Acc. to him whenever we access something in memory it is done from the starting  meaning it does not matter which element we have accessed earlier computer would first figure out the address to access and then would simply start searching it from the starting as memory has no notion about arrays

    • Alex

      If we’re talking about arrays, then yes, a[3] becomes *(a+3). That’s a direct access using pointer arithmetic, and is what is done in most cases (since we typically use [] to access array elements directly).

      However you can also do this:

      So you can access things in sequential order, if you set the code up that way.

      • Harshul

        No no no, that’s not what I meant to ask I am asking about accessibility efficiency

        What I mean is if we work on an array then all the variables are located in one section of memory so the computer can easily find them and can work with them much fast as compared to that of a linked list where all the elements are in the different sections of memory and it would take some time for computer to shift from one section of memory to another in memory in the case of linked list.

        • Alex

          It sounds like you’re talking about page faults, where the program goes to access some section of memory that has been paged out of main memory, so the OS has to go retrieve the contents of that memory before the contents can be retrieved. While linked lists probably cause more page faults than arrays (due to having a wider dispersal of addresses), at least on Windows the default page size is 4k so stuff gets paged in and out of memory all the time. Some of the apps I’m running have generated millions of page faults. While there might be some performance cost to that, it’s likely to be fairly minor on a modern operating system.

          • Harshul

            So you mean that windows accesses memory in forms of pages (which is default for windows to be 4000). But why does an OS needs to manage a whole page when it wants to just access a single element of an array it would be waste of time to manage a page to perform this task.

        • J3ANP3T3R

          are you suggesting we tell the computer where exactly to put our variables ? like int x = 1; tell the computer to put x in memory address 100 then put y in memory address 101 ?

  • Harshul

    As you said that heap memory is slower to use because the compiler does not know where and how many variables are to be defined. So is there some similar type of problems with linked list as compared to an array. Because in the linked list all the elements are not physically aligned they are connected to each other through pointers??

    • Alex

      No. Heap memory is slower because you have to access it through a pointer. Dereferencing the pointer takes additional time that does not need to be done with non-dynamic variables (those get resolved directly to an address when the program is compiled/linked, so there’s no indirection). If you allocate an array dynamically, all of the memory is still laid out contiguously, it just takes longer to do the initial memory access.

  • Harshul

    Do I need to learn assembly to learn these basic concepts like heap?

    Or there is something different that I need to do??

    • Alex

      No, you don’t need to learn assembly. In fact, you don’t even really need to know how the stack or heap work internally in order to be a competent programmer. You just need to know what they are, what purpose they serve, what their limitations are, and when it’s appropriate to use them.

  • Harshul

    One more thing, In our school we were told c-style strings. So we used that in our coding style and we did not know about the string data type being present in c++. So one day one friend of mine by mistake accessed memory more than the array limit (means if the array is of 50 elements he mistook it as of 100 elements and started using all 100 elements). When he told me, I gave him an explanation that he was able to access memory because pointer arithmetic has nothing to do with array size. I further added that he should not use it as he does not know when he will struck by invalid memory and why this time he did not struck any invalid memory is because os always allocates memory for our program where there is most of the free area. Was this explanation correct??

    But now I have figured out a different explanation, he was able to access more data as he was in the stack memory where all the memory is valid and if we try to allocate any memory through our program then we access our program’s part of memory which is already valid for use. But then what happens to the variables that we allocate, can’t the memory accessed by array (through pointer arithmetic’s mistake) colloid with that of secured for some variables. If so then would the operating system allow us to used that memory ( on shared basis as it belong to the program and is valid for use ) ??

    Another thing, As you said that heap increases it’s size depending on program’s memory needs. So is heap also allocated in such an area from where the upcoming memory( next bytes) is free because then it can grow with sequential bytes (it can use upcoming bytes rather than taking jumps of bytes in the memory). Otherwise it would have to gather bytes from different parts of memory which would make memory access slow??

    • Alex

      You’re correct about the pointer arithmetic, how it doesn’t care about array sizes, so he accessed memory off the end of the array. When you do something like this, the behavior is undefined. Since it sounds like the array in this case was allocated on the stack, and he didn’t walk off it that far, he probably stayed within “valid” memory (assigned to the program), which is why the OS didn’t terminate the program with an invalid memory access. What that memory was used for depends -- most likely he accessed an unused part of the stack memory, which may be why his program didn’t explode. But it’s possible if he declared other variables (or function parameters) after that point that he would overwrite them.

      How heap memory allocation works is complicated (particularly with operating systems that use virtual memory) and outside the scope of these tutorials. 🙂

      Heap memory access is slower than stack memory access. With variables declared on the stack, the compiler knows at compile time how the variables will be laid out in stack memory (it’s deterministic) so it can optimize the variable away and replace it with the stack memory address. However, with heap memory, the compiler doesn’t know what memory address the OS will allocate to the program. So we have to store that address in a pointer, and access it indirectly. That indirection (via dereferencing a pointer) comes at that cost of slower memory access, because we first have to get the address held by the pointer before we fetch the contents.

  • Harshul

    Hey Alex
    Before reading this tutorial, I thought that our program just uses the memory directly from the RAM with the help of operating system (os) and the stack overflow with which we dealt was because our program used the whole RAM and as a result operating system terminated the program.But as mentioned in you tutorial program already allocates memory for itself before execution which means that it must allocate heap and stack of some limited size. I agree that stack must be of fixed size so as to explain stack overflow.But is the size of heap also fixed? Because heap is defined as a large pool memory from where we can allocate memory, limited size of heap contradicts its definition.

    Second thing, What memory allocation in my view is that we request the os for memory and os reserves some part of memory under our programs name (for use) and does not allow any other program to use it. And during disallocation of memory os just removes that reservation for memory. The bytes remain in the condition. In a nutshell no changes are made to memory just os changes it’s ownership. Am I right here?

    • Alex

      Unlike the stack, the heap is not a fixed size. Most applications start with a small heap (Visual Studio executables start with a heap of 1MB, for example), and then the heap can grow as needed, until some maximum value is reached (e.g. the OS runs out of memory to give out).

      Your understanding of how the OS handles memory allocation is and deallocation is accurate. A block you deallocate could be reassigned to another application, that could (in theory) read that data in. But because this happens in a non-deterministic manner, my understanding is that it’s generally not a security issue.

  • Shiva

    Nice lesson, Alex! It’s essential that we programmers should at least have an idea of how things work under the hood.

    For anyone who wants to know the precise stack size on OS X or Linux, type ulimit -s in the terminal. It will print the stack size in MiBs. Running it on my machine (MacBook Air, OS X El Capitan) printed 8162 ~ 8MB. Agrees with what Alex said. 🙂

  • Harshul

    I have checked many tutorials explaining about stack and heap and when trying to go into depth, they all have relation with assembly language ( which I don’t know so I don’t understand ). But I must say that your tutorial is very efficient and clear in putting forward the working of stack and heap to the reader without confusing him with assembly. Great work!!!

  • JJ

    Apologize for people who don’t know how classes work, but I have a question with the memory layout and management of them.

    Lets say I have a class that has two different types of objects.

    And then inside int main I declare this super object using the new operator.

    How does the stack and the heap work for this. I know the variable super is located on the stack and it pointers to memory on the heap. Is object1 and object2 located on the heap (or the address). How does the memory layout differ for both object1 and object2.

    • Alex

      You are correct: variable super is on the stack, and points to memory on the heap (enough for a SuperObject). That SuperObject contains Object object1 (on the heap) and pointer to Object object2 (also on the heap). The allocated object2 is also on the heap.

      There’s no difference in layout for object1 and object2, the only difference is that object is instantiated directly and object2 is a pointer and the object it points to is dynamically allocated.

  • JD

  • Pofke1

    As far as I know arrays are allocated on stack and vectors are allocated on heap. So arrays are faster than vectors right? If I need one of them for ~3 000 000 objects which should I choose to enter the data and change it faster?

    • Alex

      > As far as I know arrays are allocated on stack and vectors are allocated on heap.

      It depends. Fixed arrays (e.g. int array[10], or std::array) are allocated on the stack. Dynamically allocated arrays (e.g. int *array = new int[10], or std::vector) are allocated on the heap.

      > So arrays are faster than vectors right? If I need one of them for ~3 000 000 objects which should I choose to enter the data and change it faster?

      Let’s be careful here. Allocating memory on the stack is definitely faster than allocating memory on the heap. Accessing memory on the stack may be faster than accessing memory on the heap, but it depends on a lot of factors (including how good your compiler is at optimizing code).

      The size of the stack is also limited. If you need to allocate 3 million objects, you’ll definitely want to do so on the heap, because you’ll likely overflow your stack if you allocate a fixed array that large.

      • Pofke1

        Thanks Alex!
        And another question: Can something that overflows in my program damage other that program’s data or functionality? And is there a way to know if something did overflow?

        • Alex

          Probably not. Modern operating systems will sandbox your application so it can’t impact the memory of other running applications or the operating system (both for stability and anti-malware purposes).

          However, there’s a small chance that an overflow may cause your program to malfunction, and that could theoretically cause your program could itself do something that had lasting consequence, such as corrupting a resource (e.g. a database or file) by writing bad data to it, or executing some code that has unintended negative effects (e.g. deleting file).

  • Mohammed

    Alex thx for this amazing tutorial.
    However i have a question
    int main()
      int *ptr=new int[10];
    In the above example is pointer ptr stored on heap or stack; Given that you said in the above tutorial
    int *array = new int[10]; // array is assigned 40 bytes in the heap
    which i interpreted to that both the pointer and the dynamically assigned memory are stored on the heap;

  • Matt

    Found a typo:
    "Saved copies of any registered modified by the function that need to be restored when the function returns"

    "registered" should be "registers"

  • Great! Thank you very much. 🙂

  • Rob H

    "saved copies of any registered modified by the function that need to be restored when the function returns"

    Register modified? Don’t understand what is being said.

    • Matt

      Rob, it’s saying that the values currently stored in any registers that the function will modify are copied into the stack frame before the function begins. That way, the original values can be restored when the function ends.

  • Harshul

    "Local variables are pushed onto the stack as they are defined" this statement told by you is wrong as told by stack overflows, it says that local variables are not pushed rather they are accessed sequentially as if they are stored one after another ready to be accessed by pointer arithematic

  • Harshul

    Ok i agree with your answer that size limit of heap memory is dependent on OS,RAM and other things.Can we also come up to another explaination that as stack memory is divided into several layer’s(stack frames as explained in above tutorial).So stack’s each frame’s memory also gets reduced but as heap is not divided into bunch of section so we can get much memory as compared to stack.

    I am also a little confused in your explanations first thing expressed above is that the lenght of stack and stack frames is fixed.But as we the stack frame pointer makes the difference the data below the pointer is considered to be in the stack while the rest is waste although that is in the memory but our codes connection to it is broken as our code considers that it is not there and it is popped off.

    Now what happens in case of loops do loops have their own stack which is refreshed after checking of the test condition as the loops have their own scope so it also mean that they should have their own stack.

    One more thing i did not understand your explaination for the stack in action if you can present in a more simpler way.You said "Room is made on the stack for the function’s return type" does this room has a new stack frame or it is there in called function’s stack because if it is there in the function’s stack then it would be popped off with the funtion stack and return values will never actually return.

    Another thing is that you said "Everything added to the stack after this point is considered “local” to the function" and "Local variables are pushed onto the stack as they are defined" so the local variables and other instructions are pushed on the current stack frame(funtion’s frame) as a new frame or it is added to the functions frame.The editing of function frame is not possible as it is in use and can’t be edited.Whereas if we consider that they are pushed to the frame then how can function access two local functions simultaneously like in assignment operator,as code can work on one stack at a time.

    And last one in your example of stack overflow you allocated too much memory for the stack to handle and it resulted into an overflow.So it means each frame also has an allocation limit beyond which it can not allocate memory for any variable.It means that if I use one function in my program and declare too many variables then my code is going to crash??

    • Alex

      > Now what happens in case of loops do loops have their own stack which is refreshed after checking of the test condition as the loops have their own scope so it also mean that they should have their own stack.

      Loops don’t have their own stack. Variables declared inside nested blocks are still allocated as part of the stack frame, they just aren’t accessible until they’re in the proper scope.

      I’ve updated the lesson text about the how return values are handled.

      > so the local variables and other instructions are pushed on the current stack frame(funtion’s frame) as a new frame or it is added to the functions frame

      Both parameters and local variables are included in the function’s stack frame.

      > It means that if I use one function in my program and declare too many variables then my code is going to crash??

      Yes. But in reality, this isn’t something you really need to worry about, as you’d have to declare an awful lot of variables for this to happen, or fill up your stack in some other inappropriate way first.

  • Harshul

    ->Hey one thing if i try to use any random memory location(not allocated with new operator) with the help of a pointer then it results into an error as it is invalid memory because it is in use by some other program or code.So I wanted to ask that the pointer can allocate any memory apart from the 4 categories you mentioned above i.e. any section of our ram without any restrictions.But if that memory is in use by some other code then our OS restricts the use of such memory and code crashes.

    ->The second thing that i wanted to ask is that what is the size limit of memory allocation in heap.I experimented that i can create an integer array in stack upto the size of 9999 i.e. a[999] whereas in dynamic memory allocation it was possible upto 23 times 9 without resulting into an error in code blocks gnu.So is heap infinitely long or what

    • Alex

      Pointers don’t allocate memory. The new operator allocates memory. New will only allocate memory from the heap. I think a pointer can point to memory in any of the areas, so long as it’s a section that belongs to your program (note: some areas are read-only).

      The amount of memory that can be allocated on the heap varies based on a number of factors, including OS (and whether it’s 32-bit vs 64-bit), whether the application is 32-bit vs 64-bit, physical memory (RAM), hard drive space (for paging), and what other applications are running. It’s a complicated topic that is probably better suited for an computer architecture or OS discussion.

  • Cheung Chau

    First of all, thank you for this wonderful site. I first read this site around 2008 or so. However, throughout my career, I have been a Java programmer and then a Python programmer and never really use C++ in any serious way at my work. This site from time to time, let me learn and re-learn C++. Thank you. But, one thing I think it is missing from this site and a lot of introduction book is the different between stack and heap object. Actually, I never see an introduction book mention it. The reason I notice it because in Java, you cannot create a stack object. I think it is an important topic to explore when we learn the new operator or in a section like this.

  • Pablo

    I have a doubt regarding "the stack in action".

    Suppose a function that defines variables "x" and "y", in that order. They are placed on the stack, so "y" is on top. How can the computer access "x" now? (I understood from the analogies that only the element on top could be read?)

    Thanks as always!

    • Alex

      The “element” doesn’t need to be a single value, it could be an aggregate (e.g. a structure) containing sub-elements.

      In the case of a function call, that structure would contain things like the function argument values, the return address of the caller, and local parameters….

  • quangtd

    Hi Alex,

    I have a question to heap memory. For example, heap memory which store a lot of value not be released will be clear if the program end?

    • Alex

      Generally modern operating systems will clean up all of the application memory segments (including allocated memory on the heap) when the program ends.

  • puppi

    dear alex,
    so far, i would understand all of documents but i could’nt understand this tutorial. i wonder, can you make a graphical example of stack and heap? or can you give us an example that it shows how to use stack/heap. this section of tutorial is too abstract. may be if you give a code example, that’s when we should understand.

  • Benith

    Great tutorial. Wanted to know the exact difference between stack and heap. Learnt a bit more about how function calls work as well. Thanks Alex. keep up the good work.

  • Samir

    Hi Alex,
    Thank you much for such insightful tutorial which is a very good point to start C++ I think.

    I have a question regarding accessing local variables and arguments. From your explanation it looks like we can only access content of the stack based on LIFO mechanism. That means that only last value can be accessed without destroying values on the heap. To access other values on the heap we need to destroy other variables above them.
    However since we can access local variables in any order and even change their values without affecting each other I assume there should be mechanism in addition to LIFO that allow working with local variables.
    I would say LIFO is used for creating function call related staff including local variables and other mechanism is used for working with them.

    • machello

      Each function call creates new activation record or stack frame. The stack frame contains number of local variables, parameters and the return address that the called function needs in order to return to the calling function. After the stack frame is popped, all variables in the stack frame are destroyed. Rigorously speaking, they are not destroyed. The stack pointer points to the new highest active stack frame. The destroyed stack is marked as garbage.

      • Alex

        Yes, the key point here is that we’re pushing stack frames onto the call stack, not individual local variables or parameters. We can see everything that exists in the top stack frame, which could include multiple local variables or parameters.

  • bassel

    Hi Alex. great tutorial indeed.

  • Ezo

    Hi. You can add another advantage of stack - it’s fast. Stack will be cached primarily so it’s faster than other memory places.

  • junker

    “Local variables are pushed onto the stack as they are defined.”

    Defined, or declared? Other things I read say declared.

    • Alex

      “defined” and “declared” are typically used interchangeably, as most variable declarations are also variable definitions. However, it’s probably more accurate to say they’re pushed onto the stack when the function call is executed.

  • donbright

    awesome article!

    the stack size is set on unix with the ‘ulimit’ command, which often uses ‘getrlimit’ & other functions internally.

    see also

  • Megan

    All of these tutorials are excellent - and this one in particular! I can’t tell you how many sites I’ve looked at to figure out the difference between the stack/heap and how the stack works, but this makes it so clear!

  • shorawitz

    I’m surprised this hasn’t been asked yet, but being a relative noob… I’m wondering what would be considered ” large arrays, structures, or classes”? What would a reasonable threshold be?

  • cyberlynxs

    nice explanation

  • ratep90

    Does this mean main() local variables are also on stack?

  • SWEngineer

    Simple well explained tutorial.


  • dospy

    my stack capacity is 258500 😀 ( i am on windows, 2gb ram, i dono if it matters anyways )

    #include >iostream< //this looks funny, but the forum wont let me use "”

    #define STACK_CAPACITY 258500

    struct MyStruct
    int nArray[STACK_CAPACITY];
    int main()
    MyStruct anStruct;

    char nChar;

    return 0;

    i have changed the value of STACK_CAPACITY until it reaches the limit,
    when i reached 258500, the program crashed when delcaring nChar

  • Piyush

    Why can’t we make stack as long as heap, if size becomes an issue in case of stacks?

    • Alex

      The stack has to be contiguous in memory, so it has to be preallocated. If the stack were as large as the heap, then the amount of heap memory available would be significantly reduced.

      In reality, the relatively small stack sizes are generally fine, so long as you’re aware that you shouldn’t allocate large arrays or structures on the stack, or do really deep recursion.

  • What do you mean by “register in the CPU”?
    Please simplify..

    The “marker” is a register in the CPU known as the stack pointer.

  • hello Alex,
    who decides the amount of memory among stack,heap,global & code allocated on ram &
    on what baises.

  • som shekhar

    Since malloc also allocates the size dynamically but it does on stack??? why?

  • Jeff


    This is a really good section, very helpful for me! Quick question:

    Other than writing a function or program to test limits until it crashes, is there an easier to way to determine the size, or amount of memory, allocated to the call stack for a particular program? Wouldn’t knowing this in advance help to avoid stack overflow in more complex programs?


    • I won’t say there isn’t a way to determine the stack size, but I’m not aware of how to do it.

      In reality, the stack is large enough that it’s generally not an issue as long as you’re aware that you should use dynamic allocation for anything that requires a large amount of memory.

  • Abhishek

    Where can I find the stack in my CPU box?
    Is it a separate hardware or just a space in RAM or Hard disk?

    • According to Wikipedia, “In most modern computer systems, each thread has a reserved region of memory referred to as its stack”. So it’s just RAM memory being used in a stack-like manner. As soon as the thread/program is killed, that memory can be reused for other stuff.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter