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:
| Region | Purpose | Lifetime |
|---|---|---|
| Text / Code | Compiled instructions | Entire program |
| Data | Global & static initialized data | Entire program |
| BSS | Global & static uninitialized data | Entire program |
| Stack | Function calls, local variables | Scope-based |
| Heap | Dynamic allocation | Programmer-controlled |
This naturally leads to two fundamental allocation models:
- Static allocation (Compile time)
- 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
int global_counter = 0;
- Allocated in Data segment
- Exists from program start to exit
Static Global (Internal Linkage)
static int file_private_counter;
- Visible only in this translation unit
- Still static lifetime
Static Local Variables
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
static int buffer[1024];
- Fixed size
- Fast access
- Zero fragmentation
Stack Allocation in C
assigned variables
int a = 5;
pointers: which is a variable that stores the memory address.
Wild pointer: the un-intilized pointer.
void *ptr;
Null pointer: pointer points to nothing = null or 0
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
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.
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
int* arr = (int*)calloc(10, sizeof(int));
- Zero-initialized
- Slightly slower
realloc
Resize an existing allocated memory block which is already allocated before.
arr = realloc(arr, 20 * sizeof(int));
- May move memory
- Pointer may change
- Old pointer invalid if moved
free
free(arr);
arr = NULL;
Every `malloc` must have **exactly one** `free`.
Dynamic Allocation in C++
new
// Single Object
int* p = new int(42); // 42 is initial value
delete p;
// Array
int* arr = new int[10];
delete[] arr;