CS 70

Elephant Parade, Part 4: Memory Leaks

  • Goat speaking

    Meh.

  • LHS Cow speaking

    What do you mean, "meh?" Didn't we solve the problem?

  • Goat speaking

    I say "meh" to you again! The user needs to know how many elephants they want to add beforehand.

  • LHS Cow speaking

    Okay, I can see how that could be inconvenient.

  • Goat speaking

    I think you should be able to just keep adding elephants until you want to stop.

  • LHS Cow speaking

    All right, everyone. Back to the drawing board!

"Resizing" The Array

Here's an idea:

  • Pick an initial size for the array.
  • Keep adding Elephants into the array as they arrive.
  • When we run out of space, allocate a new, bigger array.
  • Copy the contents over to the new array and continue.
  • LHS Cow speaking

    That way we can always add more Elephants.

  • Goat speaking

    I approve this plan.

Here's some code that does that. The reallocation part is highlighted.

int main() {
    constexpr size_t ELEPHANTS_TO_ADD = 2;
    size_t elephantCapacity = ELEPHANTS_TO_ADD;
    Elephant* elephants = new Elephant[ELEPHANTS_TO_ADD];

    string anotherElephant = "y";
    size_t numElephants = 0;
    while (anotherElephant == "y") {
        ++numElephants;
        cout << "Please enter elephant " << numElephants << endl;

        string name;
        cout << "Name: ";
        cin >> name;

        int age;
        cout << "Age: ";
        cin >> age;

        Elephant el{name, age};

        if (numElephants > elephantCapacity) {
            // We ran out of space, so make a bigger array
            Elephant* newElephants = new Elephant[elephantCapacity + ELEPHANTS_TO_ADD];
            // Now copy the contents
            for (size_t i = 0; i < elephantCapacity; ++i) {
                newElephants[i] = elephants[i];
            }
            // Now start using the new array
            elephants = newElephants;
            elephantCapacity += ELEPHANTS_TO_ADD;
        }
        elephants[numElephants - 1] = el;

        cout << endl << "Another elephant (y/n)? ";
        cin >> anotherElephant;
        cout << endl;
    }

    // We'll just assume this works
    sortElephantsByName(elephants, elephants + numElephants);

    cout << "The elephants are parading!" << endl;

    for (size_t i = 0; i < numElephants; ++i) {
        cout << elephants[i].getName() << " (" << elephants[i].getAge() << ")" << endl;
    }

    return 0;
}

Draw a diagram to visualize how this version works. Work through adding at least 3 Elephants, so you can see the "resize" happen.

Did you spot the problem? What is wrong with this approach?

Key Points:

  • The arrays we create stay in memory.
    • The more times we resize, the more arrays are lying around.
  • Even worse, we lose all pointers to those arrays.
    • With no pointer, we can never access them again.
  • This situation is called a memory leak.

Memory Leaks

As we saw above, a memory leak is when we have allocated memory on the heap and lost all pointers to that memory. Without pointers, we lose access to what was in that memory, but we're still occupying memory on the system, which we won't get back until our program terminates.

  • RHS Cow speaking

    Remember when we said that a pointer is like a treasure map and the data is like the treasure?

  • LHS Cow speaking

    Well a memory leak is like losing the map. The treasure's still out there, but you'll never find it.

  • Octopus speaking

    Yarr. I hate when that happens, matey. Aye…

On a small scale, memory leaks don't cause many practical problems. But when you have a leak in a loop (as in our example program), the memory usage of the program can just grow and grow the longer it runs.

Have you ever noticed that when you leave your web browser open for a really long time, it uses more and more RAM? And then when you restart it, even with all the same tabs open, it uses less? It probably has memory leaks!

Most web browsers seem to have modest memory leaks these days, but there have been some really nasty memory leaks in past versions of most major web browsers. Memory leaks in browsers become news because people tend to interact with their web browser a lot, over long periods of time.

  • LHS Cow speaking

    Just like any other incorrect behavior, it's our responsibility to prevent memory leaks in our programs.

  • Duck speaking

    So, how do we do that?

  • LHS Cow speaking

    We need to learn how to deallocate memory on the heap.

  • RHS Cow speaking

    And then we need to be careful about deallocating memory that we are done with.

(When logged in, completion status appears here.)