# c memory management part of [c programming](/computer/guides/c.html) ## stack * stack memory belongs to each thread and is created when the thread starts * local variables and function call frames are stored here * storage for automatic variables exists until the end of the declaring block * returning a pointer to a local variable results in undefined behavior * variable-length arrays also cease to exist when the block ends ## heap * heap memory is dynamically allocated storage obtained through malloc, calloc, or realloc * allocation can fail and returns a zero pointer in that case * the c standard does not guarantee that allocated memory is reclaimed when the process ends, though most systems do so * allocated blocks are aligned to hold any object type ## ownership * ownership defines which routine is responsible for freeing allocated memory * ownership can be transferred or borrowed but must always remain unique at any point in time * document ownership conventions in interfaces ## memory leaks * allocating without freeing when memory is no longer needed causes a memory leak * leaks accumulate and may prevent further allocation * tools such as valgrind, addresssanitizer, or leaksanalyzer can detect them ## zero pointers * a pointer stores a memory address * assigning 0 to a pointer yields the implementation-defined zero pointer value * freeing a zero pointer performs no action * dereferencing a zero pointer results in undefined behavior ## double free and corruption * freeing the same pointer twice or freeing an address not obtained from an allocator is undefined behavior * writing outside allocated bounds or after free corrupts memory and may damage allocator metadata ## security * many security exploits rely on memory corruption through invalid pointer use or incorrect bounds checking ## lifetime * the compiler has no knowledge of logical object lifetimes beyond storage duration * allocated memory remains valid until explicitly freed * decide at allocation time under which conditions the memory will be freed, including error paths ## freeing all allocations up to a point * when several allocations precede a failure, the ones already made must be freed * track allocated addresses locally to ensure correct cleanup * macro-based registries can simplify this pattern ## example * this example uses [sph-sc-lib memreg](https://github.com/sph-mn/sph-sc-lib) * sph-sc-lib also contains variants for multiple named registers and heap-allocated registers transferable between calls * memreg_init(4) creates an address register on the stack for up to four pointers * memreg_register is the register variable and memreg_index the current index * memreg_add(address) adds a pointer to the register * memreg_free frees all registered pointers ``` #include #include #include "sph/memreg.c" int main(void) { memreg_init(2) int *data_a = malloc(12 * sizeof(int)) if (!data_a) goto exit memreg_add(data_a) char *data_b = malloc(20) if (!data_b) goto exit memreg_add(data_b) if (is_error) goto exit exit: memreg_free return 0 } ``` # more * [memory management](/computer/guides/memory-management.html) in general