why the heap exists (lifetime not tied to scope)
Picture a function as a workspace with a desk. When the function is called, a clean desk appears; you spread your local variables out on it. When the function returns, the whole desk is cleared away in an instant — everything on it vanishes. That desk is the stack, and it is wonderfully convenient: you never clean up after yourself. But it has one hard rule. Anything on the desk is gone the moment the function ends. So how do you make something that must outlive the function that created it? That is the question the heap answers.
The heap is a separate region of the program's memory where the lifetime of an object is not tied to any scope. When you allocate on the heap, the memory stays alive across function returns, across loops, for as long as you like — until you, the programmer, explicitly free it. Concretely: if a function builds a list and wants to hand it back to its caller, it cannot build the list in local stack variables, because those die at the return. Instead it allocates the list on the heap with malloc(), and returns the pointer. The caller receives a valid pointer to memory that is still alive. The classic beginner bug is the opposite: returning the address of a local variable — a pointer to a desk that has already been cleared — which is a dangling pointer and undefined behavior.
So the heap and the stack divide the work. Use the stack for things whose life fits neatly inside one function call: it is fast and automatic. Use the heap when an object's lifetime must be decided by you, not by the call structure — when it must persist, grow, or be shared between parts of the program that come and go at different times. The price of that freedom is that the heap is not automatic: you own every allocation and must give each one back.
/* WRONG: returns a dangling pointer */ int *bad(void) { int x = 42; return &x; } /* x dies at return */ /* RIGHT: heap object outlives the function */ int *good(void) { int *p = malloc(sizeof(int)); *p = 42; return p; /* caller now owns p, frees it later */ }
The stack version returns a pointer to memory that no longer exists; the heap version returns memory that survives.
The heap here is a region of process memory for dynamic allocation — not the heap data structure (the priority-queue tree). The two share a name but are unrelated.