free() has exactly one job and exactly one rule, and this code breaks the rule twice in four lines. This question from our C Programming Quiz App closes out the memory-bug trilogy (after use-after-free and the dangling stack pointer): handing free a pointer it was never meant to see.
The Quiz Question
int a[3] = {1, 2, 3};
int *p = a;
p++;
free(p);
What is printed by this code?
- No output — runs fine
- Crash or undefined behavior
- Frees a[1] cleanly
- Compile error
The Correct Answer: Crash or Undefined Behavior
The contract of free() is strict: its argument must be exactly a pointer previously returned by malloc/calloc/realloc (or NULL, which is a no-op). p fails on both counts — it points into a stack array that was never heap-allocated, and it’s been offset by p++. Undefined behavior; in practice, the allocator notices and kills the program. Both platforms crash:
$ ./a.out (gcc 13.3, Linux) Segmentation fault (core dumped) $ ./a.out (Apple clang 21, macOS) Abort trap: 6
gcc 13 even catches it at compile time — a diagnostic worth knowing exists:
warning: 'free' called on unallocated object 'a' [-Wfree-nonheap-object]
Why Each Wrong Answer Is Wrong
Why not “runs fine”?
Modern allocators keep bookkeeping metadata next to (or hashed from) the addresses they hand out. Given an address they never issued, they read garbage metadata — glibc detects the inconsistency and aborts; macOS’s allocator does the same. Even in the unlucky case where nothing crashes immediately, the heap is now corrupted and the failure surfaces later, somewhere unrelated. “It ran fine” is the worst outcome, not the best.
Why not “frees a[1] cleanly”?
There is nothing to free — a is an automatic (stack) array whose storage is reclaimed automatically when the block ends. free doesn’t operate on individual objects or array elements at all; it releases entire heap blocks, identified by the exact address malloc returned. “Freeing an element” isn’t an operation C has.
Why not a compile error?
The types are fine: free takes a void *, and any object pointer converts to it silently. gcc’s -Wfree-nonheap-object warning shows static analysis can flag this instance, but it’s not an error — the code compiles and links on both toolchains. C trusts you with the footgun.
The Offset Trap Also Fires on Heap Pointers
The subtler half of this bug survives even when the memory is heap-allocated. Walk a malloc’d pointer forward and free the walked pointer:
int *p = malloc(3 * sizeof(int));
p++;
free(p); /* heap memory, wrong address — still UB */
$ ./a.out (glibc) free(): invalid pointer Aborted (core dumped)
gcc’s warning is delightfully precise here: “‘free’ called on pointer ‘p’ with nonzero offset 4”. The rule is free what malloc gave you — the exact address. The standard idiom keeps the original pointer sacred: iterate with a copy (for (int *q = p; ...q++)) or with indices (p[i]), and pass the untouched p to free when done. And after freeing, set the pointer to NULL — free(NULL) is harmless, so a stale double-free becomes a no-op instead of heap corruption.
Frequently Asked Questions
What happens if you free a stack variable in C?
Undefined behavior — free may only receive addresses returned by malloc/calloc/realloc. In practice glibc segfaults or reports “invalid pointer” and aborts. Stack storage is reclaimed automatically; it must never be freed manually.
Can you free a pointer that has been incremented?
No. free needs the exact address the allocator returned; an offset pointer (even by one element, even into a valid heap block) is undefined behavior. Keep the original pointer and iterate with a copy or an index.
Does free(NULL) crash?
No — the standard defines free(NULL) as a no-op. That’s why setting pointers to NULL immediately after freeing them is cheap insurance against double-free bugs.
Related Reading
- Use After Free in C – Why Freed Memory Bites Back
- Returning a Pointer to a Local Variable in C
- Negative Array Index in C – p[-1] from an Offset Pointer
- Pointers in C – Complete Guide
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
This question is #150 in the C Programming Quiz App — 155 questions with explanations covering memory, pointers, undefined behavior, and more.
Download on Google Play →