Pointers and Memory

Dynamic Memory Management

Dynamic storage is needed when an object's size or lifetime cannot be fixed at compile time.

What is Dynamic Memory Management?

Dynamic storage is needed when an object's size or lifetime cannot be fixed at compile time.

Allocate a runtime-sized array and release it safely.

Important points

  • Every pointer must refer to a live compatible object or be null.
  • Pair each owned allocation with exactly one release.
  • Prefer clear ownership and const-correct interfaces.

C and C++ code examples

C
Run code →
main.c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    size_t count = 5;
    int *values = calloc(count, sizeof *values);
    if (!values) return 1;
    for (size_t i = 0; i < count; ++i) values[i] = (int)(i * i);
    printf("last=%d\n", values[count - 1]);
    free(values);
    return 0;
}
Expected output
last=16
C++
Run code →
main.cpp
#include <iostream>
#include <vector>

int main() {
    std::vector<int> values(5);
    for (std::size_t i = 0; i < values.size(); ++i) values[i] = static_cast<int>(i * i);
    std::cout << "last=" << values.back() << '\n';
}
Expected output
last=16

C and C++ comparison

C requires matching calloc or malloc with free and checking allocation failure. A C++ vector owns its memory, releases it automatically, and remains safe if an exception occurs.

C

Ownership and cleanup are conventions enforced by the programmer.

C++

Containers and RAII types can encode ownership and cleanup in object lifetimes.

Practice exercises

Run both versions, then modify them to observe the different language guarantees.

  • Test null and allocation-failure paths.
  • Run with AddressSanitizer and UndefinedBehaviorSanitizer.
  • Document whether every pointer owns or only observes its object.