CODE: C CPP Memory

Before talking about allocation techniques, we must understand where memory comes from, Memory is the physical storage where a program’s instructions, data, and state live while it runs.

What Is Memory

Memory is the physical storage where a program’s instructions, data, and state live while it runs.

The CPU does not “see” variables or objects.

It sees addresses and bytes.

Everything in C and C++—variables, arrays, objects, stacks, heaps—exists only as:

  • a memory address
  • a size
  • a lifetime

Understanding memory allocation is therefore not an “advanced topic” — it is the foundation of correct, fast, and safe software.


The Process Memory Layout

A typical C/C++ program is divided into regions:

RegionPurposeLifetime
Text / CodeCompiled instructionsEntire program
DataGlobal & static initialized dataEntire program
BSSGlobal & static uninitialized dataEntire program
StackFunction calls, local variablesScope-based
HeapDynamic allocationProgrammer-controlled

This naturally leads to two fundamental allocation models:

  1. Static allocation (Compile time)
  2. Dynamic allocation (Run time)

Choosing _how_ memory is allocated directly affects:

  • Performance
  • Determinism
  • Safety
  • Cache behavior
  • Fragmentation
  • Scalability

Rule of thumb:

Memory mistakes in C/C++ don’t fail loudly — they fail silently.

So let’s start where memory begins.


Static Memory Allocation

it is the data in Data, BSS memory segments.

Static memory allocation means:

  • Memory size is known at compile time
  • Memory address is fixed
  • Memory lifetime is entire program execution

No runtime decision.

No allocation overhead.

No failure.

Use static allocation when:

  • Size is known and fixed
  • Lifetime spans the whole program
  • Determinism is required (embedded / RTOS)
  • Performance is critical
  • Memory must never fail

Static Allocation in C

Global Variables

c
int global_counter = 0;

  • Allocated in Data segment
  • Exists from program start to exit

Static Global (Internal Linkage)

c
static int file_private_counter;

  • Visible only in this translation unit
  • Still static lifetime

Static Local Variables

c
void increment(void) {
    static int count = 0;
    count++;
    printf("%d\n", count);
}

Why this exists:

To preserve state across function calls without heap allocation.

Static Arrays

c
static int buffer[1024];

  • Fixed size
  • Fast access
  • Zero fragmentation

Stack Allocation in C

assigned variables

c
int a = 5;

pointers: which is a variable that stores the memory address.

Wild pointer: the un-intilized pointer.

c
void *ptr;

Null pointer: pointer points to nothing = null or 0

c
void *ptr = ((void *)0);
void *ptr = NULL;

Dangling Pointer: when the object deleted or de-allocated, and the pointer still exist.

Static Allocation in C++

C++ adds object lifetime semantics on top.

Static Objects

cpp
struct Logger {
    Logger() { std::cout << "Init\n"; }
    ~Logger() { std::cout << "Destroy\n"; }
};

static Logger logger;

  • Constructor runs before main()
  • Destructor runs after main()
  • Order across translation units is not guaranteed

> Static Initialization Order Fiasco, This problem alone is why large C++ systems avoid global statics.


Why Static Allocation Is Fast:

  • No system calls
  • No locks
  • No bookkeeping
  • Perfect cache locality
  • Zero fragmentation

But nothing is free.

Limitations of Static Allocation

Static memory cannot:

  • Grow or shrink
  • Be conditionally created
  • Be freed early
  • Handle unknown sizes

So what happens when size or lifetime is not known?

We move to dynamic allocation.


Dynamic Memory Allocation

Dynamic allocation means:

  • Memory size decided at runtime
  • Memory taken from the heap
  • Lifetime controlled manually

This gives flexibility — but introduces risk.

You need dynamic allocation when:

  • Size depends on input or runtime state
  • Lifetime exceeds a single scope
  • Objects must outlive function calls
  • Data structures grow (lists, trees, maps)

Dynamic Allocation in C

malloc

Allocate memory from heap but does not initialize it.

c
int* arr = (int*)malloc(10 * sizeof(int));
if (arr == NULL) {
	printf("Memory allocation failed\n");
	return 1;
}

  • Uninitialized memory
  • Fast but dangerous

calloc

Allocate memory from heap and initializes it to 0

c
int* arr = (int*)calloc(10, sizeof(int));

  • Zero-initialized
  • Slightly slower

realloc

Resize an existing allocated memory block which is already allocated before.

c
arr = realloc(arr, 20 * sizeof(int));

  • May move memory
  • Pointer may change
  • Old pointer invalid if moved

free

c
free(arr);
arr = NULL;

Every `malloc` must have **exactly one** `free`.

Dynamic Allocation in C++

new

cpp
// Single Object
int* p = new int(42); // 42 is initial value
delete p;

// Array
int* arr = new int[10];
delete[] arr;