Understanding Stack Overflow and Heap Overflow in C Language: The Simplest Explanation Online

Content

First, imagine memory as a three-story building:

  1. The first floor is the “Global Data Area” – the hall you see as soon as you enter;
  2. The second floor is the “Stack” – like a hotel front desk with a last-in-first-out drawer cabinet, opened and closed as needed;
  3. The third floor is the “Heap” – like an underground warehouse, where you have to find the manager (malloc) to store boxes, and you must move them out yourself when done (free).

Next, let’s clarify the two types of “overflow” using everyday metaphors.

1. Stack Overflow

  1. Scenario analogy The hotel front desk has only 100 drawers (limited stack size). The staff (compiler) processes according to the “last in, first out” rule:
  • Each time a function is called, a “task list” (saving return address, local variables) is placed in the drawer.
  • When the function returns, the topmost task list is removed. If a function (or recursion) keeps adding to it, the 100 drawers will fill up instantly, and adding one more will cause a “bang” – the drawer breaks. This is stack overflow.
  1. Common code example
void recurse() {
    char buf[10000];     /* Each call consumes 10 kB */
    recurse();           /* Infinite recursion, drawer fills up instantly */
}

Result: The program crashes directly, and the operating system usually throws a <span>Segmentation fault</span> or <span>Stack Overflow</span>.

  1. Trigger conditions
  • Infinite/deep recursion;
  • Requesting a very large array on the stack at once, such as <span>char buf[8 * 1024 * 1024];</span> (8 MB exceeds the default stack of 1–8 MB).
  1. How to avoid
  • Move large arrays to the “underground warehouse” (heap):
    char *buf = malloc(8000000); /* Use heap, stack is not burdened */
    
  • Use loops instead of deep recursion;
  • Compiler options like <span>-fsplit-stack</span>, adjust system stack size (Linux uses <span>ulimit -s</span>).

2. Heap Overflow

  1. Scenario analogy The underground warehouse is large, but the manager only allocates you a fixed-size box.
  • You requested a box with 10 slots (<span>malloc(10)</span>).
  • You wrote data for 20 items, resulting in overlapping with someone else’s box.
  • When someone comes to pick up their goods, they find the items in the box are crushed, causing the program to error. This is heap overflow.
  1. Common code example
char *p = malloc(10);
strcpy(p, "This string is way too long!"); /* Wrote 29 bytes, overflowed by 19 bytes */

Consequences:

  • May corrupt the management information of the adjacent heap block, causing a crash during <span>free()</span>;
  • Attackers can carefully construct data to control program flow (classic “heap exploitation”).
  1. Trigger conditions
  • Writing more data than the allocated heap block size;
  • Reading out of bounds may also lead to information leakage.
  1. How to avoid
  • Measure size before writing:
    size_t len = strlen(src) + 1;
    char *p = malloc(len);
    if (p) memcpy(p, src, len);
    
  • Use safe functions:<span>strncpy</span>, <span>snprintf</span>, <span>strlcpy</span> (or more modern <span>strdup</span>).
  • Enable compiler protections:<span>-fsanitize=address</span> (ASan) can detect out-of-bounds at runtime.
  • Develop the habit of pairing “who mallocs, who frees” to avoid double writing to freed blocks.

In summary

  • Stack overflow: The “drawer cabinet” of function calls is filled to the brim – usually due to too deep recursion or too large local variables.
  • Heap overflow: Writing into someone else’s box in the underground warehouse – usually due to out-of-bounds writes or reads after malloc.

Remember: The stack is like a narrow vending machine, while the heap is like a spacious warehouse that requires self-discipline; using them incorrectly will lead to “overflow” explosions.

Leave a Comment