Stack memory
Summary
Along with heap memory heap memory, programs make use of stack memory during runtime.
Best suited for small-sized singular values that are temporary/ephemeral rather than large or complex data types that need to persist for a longer time.
Specifically used to keep track of memory used during function executions within a given scope: control flow, local variables, returned value.
Uses a LIFO data-structure
Similarly to the stack data structure, it works on the basis of LIFO: the last item put on the stack is the first item to be withdrawn.
Note, this doesn’t mean that the data at the memory addresses that comprise the stack can only be accessed in a LIFO manner. Any item currently on the stack can be accessed (be read or modified) at any time. LIFO applies when it is is time to clear memory from the stack: the most recent addition is cleared first from the top down.
Stack pointer
A stack pointer is used to manage the items in the stack. This value is stored in a register and its value is the memory address of the item currently on the top of the stack. Note: not the value itself, the address of the value.
When a new value is added to the top of the stack, the pointer’s value is adjusted to increase the size of the stack and make room for the new value. So this will be a new memory address for the latest item. When an item is removed, the reverse happens. The previously top address is cleared and the pointer points to the new top item.
Threads
For every thread that a program spawns, it gets its own stack or “stack frame”. Stack memory within the thread can only be accessed by processes within that thread which is what makes it well suited for managing scoped function memory.
Role in program execution
Function call management: a stack records the key information pertaining to the execution of a function: parameters, local variables, the location of the address for the returned value.
Local variable storage: storing the variables local to a function’s scope and removing them once the function returns, avoiding memory leaks
Control flow: record from where a function is called and where its return value should be stored, meaning the right value is always returned no matter how nested it is.
Recursion: individuating each call of a function that calls itself and its given step to avoid infinite loops