Allocation means "reserving some memory for a program to use". There are three main ways to do it, and each has its own speed, lifetime and risks.

7.1 Static Allocation (Compile Time)

What it is: Memory whose size and place are decided before the program even runs, by the compiler (the tool that turns source code into a program). This is the mechanism behind the data segment from Section 6.3.

int globalCounter = 0;        // static allocation — exists for the
                               // entire program lifetime, fixed size

Characteristics:

  • The size must be known when the program is built
  • Allocated once, for the whole life of the program
  • No runtime cost: nothing is "requested" while the program runs; the space is simply set aside when the program loads

7.2 Stack Allocation (Function Scope)

What it is: Memory that is given automatically when a function starts and freed automatically when it returns. This is the mechanism behind the stack frames from Section 6.1.

void doWork() {
    int x = 5;          // stack-allocated: exists only inside doWork()
    char buffer[100];   // also stack-allocated
}   // both are automatically freed here, the instant the function returns

Characteristics:

  • Extremely fast: giving out stack space is often just moving one pointer (the stack pointer register from Chapter 2, Section 8.3)
  • Automatic lifetime: tied strictly to the function call. No manual cleanup is needed (or possible)
  • Limited size: a very large local array can overflow the stack's fixed size (Section 8.4)

7.3 Heap Allocation (malloc, new, etc.)

What it is: Memory requested at run time, when the size may not be known until the program is running. It lasts until it is explicitly released (in "unmanaged" languages like C) or until nothing refers to it any more (in garbage-collected or "managed" languages such as C#, Java or JavaScript). A garbage collector is a helper in the language's runtime that finds and frees memory nobody uses any more.

int* data = malloc(count * sizeof(int));  // C: explicit heap allocation
...
free(data);                                // C: explicit heap release
var data = new int[count];  // C#/.NET: heap allocation, but the
                             // .NET garbage collector automatically
                             // frees it once nothing references it anymore

Characteristics:

  • Slower than the stack: the memory allocator (part of the runtime or the OS) has to search for, and keep track of, a suitable free block
  • Flexible lifetime: the data can outlive the function that made it, be passed around, and be freed at any later time
  • Needs bookkeeping: the allocator must track which parts of the heap are in use and which are free. That is exactly where the next two problems come from
StaticStackHeap
When decidedBefore the program runsWhen a function startsWhile running
FreedWhen the program endsWhen the function returnsBy you, or by the garbage collector
SpeedNo runtime costExtremely fastSlower
RiskSize fixedStack overflowFragmentation and leaks

7.4 Heap Fragmentation

What it is: A state where the heap has enough total free memory for a request, but the free memory is scattered in small separate pieces instead of one usable block. So the request still fails, or the heap has to grow when it did not need to.

Analogy: A car park with 8 free spaces, but all spread out between parked cars. A bus that needs 6 spaces in a row cannot park, even though 8 spaces are free.

Heap after many allocations and frees:
┌────┬──────────┬────┬────────┬────┬──────────┬────┐
│used│   free   │used│  free  │used│   free   │used│
│1KB │   3KB    │2KB │  2KB   │1KB │   3KB    │1KB │
└────┴──────────┴────┴────────┴────┴──────────┴────┘

Total free memory: 8 KB
But a request for a single contiguous 6 KB block FAILS —
no single free chunk is big enough, even though 8 KB total exists

Why it happens: A program takes and frees blocks of many sizes over time. Freed memory does not join back into big blocks by itself, so it ends up as a patchwork of gaps. Long-running programs (services, servers, apps left open for days) suffer most, because fragmentation builds up over the process's life.

Fixes: Allocators use several tricks to reduce it (best-fit, coalescing adjacent free blocks into one bigger block, and size-class "buckets"). Some managed runtimes also periodically compact the heap: they physically move live objects together to remove the gaps completely. A garbage collector can do this because it can update every reference to a moved object. That is much harder in unmanaged languages.

7.5 Memory Leaks (Allocated But Not Freed)

What it is: Memory that was allocated on the heap, but every reference (pointer) to it has been lost. The program can no longer free it and can no longer use it, yet the OS still counts it as "in use" by that process.

void leaky() {
    int* data = malloc(1000);  // allocate 1000 bytes
    return;                    // function returns — 'data' pointer is gone
                                // but the memory was never freed!
                                // This 1000 bytes is now leaked — permanently
                                // unreachable until the process exits
}

Why it matters: One small leak is often harmless. But a leak in code that runs again and again (a loop, a function called often, a long-running service) adds up. The process's memory use climbs steadily, hour after hour, until the PC runs low on memory and starts paging heavily (Section 5.5), or the process fails to allocate and crashes.

How it is found in practice: In Task Manager, you see a process whose memory only ever climbs and never really drops during a long session. That is a strong clue to look for in this chapter's lab and in real troubleshooting.

Garbage-collected languages do not remove leaks completely: Even in C#, Java or JavaScript a leak can happen. It is not from forgetting free(), but from accidentally keeping a reference alive somewhere (a list that keeps growing, an event handler that is never unsubscribed). That stops the garbage collector from ever reclaiming the object, even though the program no longer really needs it.

Summary

TopicRemember this
Static allocationFixed at build time; lives for the whole program
Stack allocationAutomatic, extremely fast, freed on return; limited size
Heap allocationFlexible lifetime, slower, needs bookkeeping
FragmentationEnough total free memory, but not in one piece
Memory leakAllocated but no longer reachable or freed; memory use only climbs