Dynamic Memory Management

use-after-free

You return a library book, and then the next day you scribble a note in its margin out of habit — except the book is no longer yours, and someone else has already borrowed it. Your note now lands in a stranger's book. Use-after-free is the programming version: you call free() on a block, and then you read or write through a pointer that still points at that now-freed block. The memory may already have been handed to a different malloc and be holding something else entirely.

Precisely: after free(p), the pointer p is a dangling pointer — it still holds the old address, but the allocator now considers that memory available and may reuse it for the next allocation request. Reading through p afterward gives you whatever happens to be there now (possibly the old data by luck, possibly a different object's bytes). Writing through p corrupts whatever now occupies that memory. Both are undefined behavior: the C standard places no requirements on what happens, so the program might appear to work, might crash immediately, or might corrupt data silently and crash much later somewhere unrelated. That delay between the mistake and the symptom is what makes use-after-free one of the hardest bugs to track down.

It is also one of the most dangerous from a security standpoint. Attackers exploit use-after-free by arranging for an allocation they control to be placed in the freed block, so that the stale pointer now reads or writes attacker-chosen data — a common route to taking over a program. The defense is discipline: set a pointer to NULL immediately after freeing (so a stray use becomes a clean NULL dereference, easier to catch), keep ownership clear so you never free memory another part of the code still relies on, and run tools like AddressSanitizer or Valgrind, which detect access to freed blocks.

char *p = malloc(16); free(p); p[0] = 'x'; /* USE-AFTER-FREE: writing into freed memory (undefined behavior) */ /* Safer: free(p); p = NULL; then p[0] = 'x' is a clean NULL deref, easy to spot */

After free, p is dangling; touching it is undefined behavior. Nulling p turns a silent corruption into an obvious crash.

It may seem to work because the freed bytes still hold the old value — that is luck, not correctness. The same code can corrupt or crash the moment the allocator reuses the block.

Also called
UAFdangling-pointer use懸置指標存取