What is the Heap

beginner c++11 memory

All variables in C++ use a portion of the memory of your computer. C++ has two basic forms of memory: the stack and the heap. The heap is where non-local (but not global) variables are stored in memory. Non-local here means heap variables are not tied to scopes unlike stack variables. The heap is intertwined with pointers and in fact cannot be used without them. To create a variable “on the heap” in C++ we use the new keyword which returns a pointer. To destroy a variable on the heap in C++ we use the delete keyword which accepts one pointer. Here’s an example:

#include <iostream>

int main() {
  int* a = new int(5);
  std::cout << "*a: " << *a << " a: " << a << "\n";
  delete a;
}
*a: 5 a: 0x7fc24b405a40

Manual Memory Management

C++ manages coordinating with the operating system to create the heap, manage its size, and place variables when you call new. However, explicit management of heap variables is necessary in your program and is not automatic in C++. C++ is well known for requiring manual memory management and it’s all because of the heap. While technically correct it’s no the full story.

There are many tools in C++’s Standard Library to help programmers with direct heap management such as std::unique_ptr and std::shared_ptr. Additionally, many objects in C++ such as std::vector and std::unordered_map manage the memory they own by calling delete in their destructors when needed. You can do this as well with your own objects and you should! Using destructors and objects on the stack allows other code to not need to worry about calling new and delete. Here’s an example:

#include <iostream>

// Create a single int on the heap
class HeapInt {
public:
  explicit HeapInt(int i) {
    std::cout << "new int\n";
    i_ = new int(i);
  }

  ~HeapInt() {
    std::cout << "delete int\n";
    delete i_;
  }

  int& value() {
    return *i_;
  }

private:
  int* i_;
};

int main() {
  HeapInt a(5);
  std::cout << "a.value(): " << a.value() << "\n";

  {
    HeapInt b(7);
    std::cout << "b.value(): " << b.value() << "\n";
  }
}
new int
a.value(): 5
new int
b.value(): 7
delete int
delete int

Memory Leaks

C++’s heap is where memory leaks happen. A memory leak is when your program has allocated memory from the heap by calling new but then doesn’t call delete before all pointers to that memory go away. When this happens the heap memory becomes unreachable and there’s no way for your program to get a pointer to it again. If this happens often enough while your program is running eventually your operating system will refuse to provide more memory when calling new and your program will likely crash. Unfortunately when calling new it can be easy to miss calling delete when the code is so complex that it’s difficult to understand all the possible paths it could take. Here’s an example of what leaking memory looks like:

#include <iostream>

void foo(int i) {
  int* a = new int(i);
  std::cout << "*a: " << *a << " a: " << a << "\n";
  // LEAK!
}

int main() {
  for (int i = 0; i < 5; i++) {
    foo(i);
  }
}
*a: 0 a: 0x7fe5a7405a40
*a: 1 a: 0x7fe5a7405a50
*a: 2 a: 0x7fe5a7405a60
*a: 3 a: 0x7fe5a7405a70
*a: 4 a: 0x7fe5a7405a80

Thankfully there’s many tools to help with not leaking in the first place in the C++ Standard Library. Outside the language itself there’s developer tools for catching and fixing memory leaks that do happen.


For more C++ By Example, click here.