Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Pointers and References  ›  Lesson

The Memory Model: Stack, Heap and Static

Memory Model 12 minEvery C++ object has a storage duration that decides when its memory is released: automatic objects at the end of their scope, dynamic objects when their owner frees them, and static objects at program exit.

The Memory Model: Stack, Heap and Static

Rocket Run keeps a few numbers for a moment, one high score for the whole session, and a level full of asteroids whose count is only known after the level file loads. These three needs map onto three kinds of storage, and knowing which one an object uses tells you exactly when it disappears.

The rule

Braces end locals, owners end heap objects, program exit ends statics.

Every object occupies some bytes, has an address, and has a storage duration:

  • Automatic (usually called the stack): ordinary local variables. Created when the line runs, destroyed at the closing } of their scope. Fast and automatic.
  • Dynamic (usually called the heap): objects you create at run time, whose size or lifetime is not known in advance. They live until their owner releases them.
  • Static: globals and static locals. Set up once, and they last until the program ends.
void playLevel(int asteroidCount) {
    int lives = 3;                                  // automatic
    static int highScore = 0;                       // static: kept between calls
    std::vector<Asteroid> rocks(asteroidCount);     // the vector's elements live on the heap
    auto boss = std::make_unique<Boss>();           // heap object, owned by boss
}   // lives, rocks and boss end here, and rocks and boss free their heap memory

In modern C++ you rarely touch the heap by hand. std::vector, std::string and std::make_unique allocate for you and free the memory when they themselves are destroyed. The raw version, new with a matching delete, is easy to get wrong: forget the delete and the memory leaks.

You can ask any type how many bytes it takes with sizeof. sizeof(char) is always 1; most other sizes depend on the platform.

The shortcut

For any object, ask one question: who decides when it dies?

Sorting Rocket Run's objectsStep 1 of 4
  1. int lives inside playLevel

    Its closing brace decides. Automatic storage.

The trap is keeping the address of an automatic object after its scope has ended. The memory is reused, and using that address is undefined behaviour.

Drills

Answer fast — trust the rule.

quick drill

Where does int lives = 3; inside a function live?

quick drill

How long does static int highScore = 0; inside a function last?

quick drill

When is heap storage the right choice?

quick drill

What is sizeof(char)?

quick drill

A function returns the address of one of its local int variables. What is wrong?

Remember

  • Braces end locals, owners end heap objects, program exit ends statics.
  • Shortcut: ask who decides when the object dies.
  • Trap: never keep the address of a local after its scope ends.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWhere the boss lives

Rocket Run creates the local int lives = 3; inside a function, keeps a static int highScore inside another function, and creates a boss with std::make_unique<Boss>() whose size is only known after loading a level file. Explain where each lives, when each is destroyed, and why the boss is on the heap.