5.1.18 · D1C Programming

Foundations — Common memory errors — null dereference, buffer overflow, use-after-free, double free, memory leak

2,454 words11 min readBack to topic

Before you can understand a single memory error, you must be able to read every symbol the parent note throws at you without flinching. This page builds each one from absolutely nothing, in an order where every idea rests on the one before it. If you have never written a line of C, start here and do not skip.


0. The picture everything sits on: memory as a row of boxes

Figure — Common memory errors — null dereference, buffer overflow, use-after-free, double free, memory leak

Look at the figure. The boxes are drawn as a horizontal strip. The little number under each box (0, 1, 2, 3, …) is its address — this never changes. The value inside the box is the data, and that can change any time you write to it.

Why the topic needs this: every single error — null deref, overflow, use-after-free — is about which box number you touched. If you cannot see the row of numbered boxes, none of the errors make sense. This picture is the ground floor.


1. The symbol byte and the range 0–255

Picture: one box in the strip above. Why 0–255? A byte is 8 on/off switches (bits); combinations, counted from 0, gives you 0 through 255. We won't need bit-level detail here — just know "one box = one byte = a number ≤ 255".

Why the topic needs it: when the parent note says char buf[8] it means 8 boxes in a row. When it says a string needs "12 bytes", it means 12 boxes. Buffer sizes are counted in bytes.


2. A variable — a named box

Picture: take one box in the strip, draw a name tag x hanging off it. You say x = 7; and the number 7 goes inside that box.


3. int, char — how many boxes and what shape

Picture: an int is four neighbouring boxes fenced together and treated as one value.

Why the topic needs it: sizeof(int) appears everywhere in the parent — it's literally "how many boxes does one int need?" (the answer, usually, is 4). And malloc(sizeof(int) * 1000) means "give me enough boxes for 1000 ints".


4. & — "the address of" (the box number)

Picture: point at the box named x, then read the little number printed underneath it. That number is &x.

Why the topic needs it: this is where a value lives. To make a pointer point at something, you copy its address with &.


5. Pointer and the * in a declaration

This is the star of the whole topic. Build it slowly.

Figure — Common memory errors — null dereference, buffer overflow, use-after-free, double free, memory leak

In the figure: x is an ordinary box holding 7 at address 100. p is another box, and the value stored inside p is the number 100 — drawn as a red arrow reaching over to point at x. That arrow is the whole idea of a pointer.


6. *pdereference (follow the arrow)

Picture: stand on p, read the number inside it (100), walk to box #100, open it. *p is now that box. *p = 42; writes 42 into x. printf("%d", *p); reads x's value.

Why the topic needs it: "null dereference" = following an arrow pointing at box #0. "use-after-free" = following an arrow to a box you already gave back. The word dereference is in three of the five error names.


7. NULL and address 0

Picture: a pointer with an arrow drawn as a crossed-out "🚫" instead of reaching a box — it points at the reserved, forbidden box #0.

Why the topic needs it: the operating system leaves box #0 (and its neighbourhood) unmapped — untouchable — precisely so that following a NULL arrow crashes immediately (a segfault) instead of silently corrupting data. That controlled crash is the parent's whole trick of "set p = NULL; after free so a later *p is detectable".


8. Stack vs Heap — two neighbourhoods of boxes

Figure — Common memory errors — null dereference, buffer overflow, use-after-free, double free, memory leak

The figure shows one strip split in two: the stack side (auto-managed) and the heap side (the red block is a chunk you rented). Buffer overflows on the stack can smash a saved return address (a security disaster); leaks and double-frees happen on the heap.

Why the topic needs it: the five errors live in different neighbourhoods. Knowing which region a box is in tells you whether the cleanup is automatic (stack) or your job (heap). See Stack vs Heap Memory.


9. malloc and free — renting and returning heap boxes

Picture: malloc hands you a red-outlined block on the heap and a slip of paper (p) pointing at its first box. free(p) un-reserves the block — but your slip still has the number on it (now a dangling arrow). See malloc and free.


10. Arrays, [], and the string terminator \0

Picture: 8 boxes fenced together; a red marker on the box at offset i. Step past box 7 and you're trampling the neighbour's boxes → overflow.

Why the topic needs it: "hello world" is 11 letters, so it needs boxes. Into a char buf[8] (only 8 boxes) it overflows by 4 — exactly the parent's example.


11. Undefined Behaviour — why "it worked on my machine" proves nothing

Picture: a box you don't own, touched — with three arrows leaving it labelled "crash", "corrupt", "seems fine". You don't get to pick which. See Undefined Behaviour.

Why the topic needs it: this is why memory errors are so nasty. They aren't polite exceptions — a use-after-free might print the right answer today and delete a file tomorrow.


How these foundations feed the topic

Memory as numbered boxes

Byte and value 0 to 255

Address with the and operator

Variable a named box

Pointer holds an address

Dereference follow the arrow

NULL points at box zero

Stack vs Heap regions

malloc and free rent and return

Array index and null terminator

Undefined Behaviour

The five memory errors

Every arrow in that map is a prerequisite: you cannot understand the five errors until every node above L is solid. Related build-up notes: Pointers in C, malloc and free, Stack vs Heap Memory, Undefined Behaviour, and later Valgrind and AddressSanitizer and Buffer Overflow Exploits.


Equipment checklist

Cover the right side and answer out loud; reveal to check.

What is an address?
The permanent number of a box in memory — where it is, not what it holds.
What are the two things every variable box has?
An address (where it lives) and a value (what's currently inside).
What does &x give you?
The address (box number) of the variable x.
In plain words, what is a pointer?
A variable whose value is an address — a slip of paper with a box number on it.
What does *p do in an expression?
Follows the arrow: goes to the box whose number p holds, and reads/writes that box.
What is the numeric value of NULL, and why does touching it crash?
Address 0; the OS leaves box 0 unmapped, so dereferencing it traps immediately.
Who cleans up stack boxes vs heap boxes?
Stack: automatic on function return. Heap: you must free it yourself.
What does malloc(n) return, and what on failure?
The address of the first of n new heap boxes; NULL if it couldn't allocate.
Does free(p) change the value stored in p?
No — p keeps the old (now dangling) address; only the block is returned.
For char buf[8], what is the last legal index?
7 (indices run 0 to 7 — one less than the size).
Why does a string of L letters need L + 1 boxes?
The extra box holds the terminating \0 (value 0) that marks the string's end.
What is Undefined Behaviour?
Behaviour the C standard imposes no requirements on — may crash, corrupt, or seem to work.