What is the difference between stack and heap memory in C?
The stack holds locals and call frames, freed automatically on return; it is fast and small (8 MB for the main thread on most Linux systems, 1 MB on Windows by the linker default, 128 KiB for new threads on musl). The heap holds
mallocmemory that lives untilfree. Use the heap when the size is known only at runtime or the data must outlive the function. See stack vs heap.What is the difference between
malloc,callocandrealloc?All three return
NULLon failure.malloc(size)gives uninitialized memory,calloc(count, size)zeroed memory, andrealloc(p, size)resizes a block, moving it if needed.C#include <stdio.h> #include <stdlib.h> int main(void) { int *a = calloc(4, sizeof *a); /* 4 ints, all zero */ if (!a) return 1; for (int i = 0; i < 4; i++) a[i] += i; int *bigger = realloc(a, 6 * sizeof *a); /* grow to 6 ints */ if (!bigger) { free(a); return 1; } a = bigger; a[4] = 40; a[5] = 50; /* new part is uninitialized, so set it */ for (int i = 0; i < 6; i++) printf("%d ", a[i]); printf("\n"); free(a); return 0; }It prints
0 1 2 3 40 50.callocreturnsNULLifcount * sizeoverflows (mainstream libcs check it and C23 requires it). See calloc and realloc.Practice it: Merge Sorted Array
What is wrong with
p = realloc(p, new_size);?If
reallocfails it returnsNULLand keeps the old block, so assigning straight topleaks it.int *tmp = realloc(p, new_size); if (tmp == NULL) { /* p is still valid: report the error, keep or free p */ free(p); return -1; } p = tmp;Avoid
realloc(p, 0)too: glibc freespand returnsNULL, musl returns a non-null pointer to a minimal block, and C23 makes the call undefined (see realloc on cppreference).What is a memory leak, and how do you find one in C?
A leak is heap memory still allocated that the program can no longer reach, because the last pointer to it was lost before
free.void leak(void) { char *buf = malloc(100); if (!buf) return; if (something_failed()) return; /* buf is leaked on this path */ free(buf); }Find leaks with Valgrind (
valgrind --leak-check=full ./app) or AddressSanitizer (gcc -fsanitize=address -g). Avoid them with one owner per allocation and a single cleanup path (goto cleanup;). See memory leaks.What happens if you call
freetwice on the same pointer, or use memory after freeing it?Both are undefined behavior. A double free can corrupt the allocator's lists, which attackers exploit; use after free touches memory that may belong to another allocation.
free(NULL)does nothing, so setting the pointer toNULLafterfreemakes a secondfreeharmless. AddressSanitizer reports both bugs at the exact line.Why is returning the address of a local variable a bug?
The local's stack frame is released on return, so the pointer dangles and reading through it is undefined behavior.
char *bad_name(void) { char name[16] = "coddy"; return name; /* GCC warns: function returns address of local variable */ }Let the caller pass a buffer instead (the standard library's usual choice), or return
mallocmemory the caller frees.What causes a segmentation fault in C?
The operating system stops a process that touched memory it may not access. In C it is a symptom of undefined behavior: dereferencing
NULLor an uninitialized pointer, writing to a string literal, going past an array, using freed memory, or a stack overflow. An out-of-bounds write inside your own memory may not crash at all. Debug with-fsanitize=address, orgdbandbt. See segmentation faults.Describe the memory layout of a C program.
From low to high addresses on Linux: text (machine code), data (globals and statics with a non-zero initializer), BSS (zero or uninitialized ones, zeroed at startup and taking no space in the file), the heap growing up, shared libraries and
mmapregions, and the stack growing down. Sostatic int big[1000000];grows BSS but not the executable; with= {1}the file grows by 4 MB.How does
mallocwork, and how doesfreeknow the size of the block?It depends on the libc. glibc keeps a small header before each block with its size, and
free(p)reads the bytes beforep; musl's mallocng and jemalloc find the size from the group or page the address belongs to. Either way, pass back exactly whatmallocreturned. Freed blocks go to free lists or size-class bins for reuse, and glibc serves requests above a threshold (128 KiB at start, adjusted at run time) with their ownmmap, returned to the kernel onfree.What does
malloc(0)return?It is implementation-defined: either
NULL, or a unique pointer you must not dereference but mustfree. glibc and musl return non-NULL, but portable code cannot rely on it, so a size that can be 0 needs its own check.size_t n = count_items(); int *items = malloc(n * sizeof *items); if (items == NULL && n != 0) { /* a real allocation failure */ }Otherwise an empty list looks like an allocation failure.
C Memory Management Interview Questions
Dynamic allocation, stack and heap, leaks and the mistakes that cause crashes.
10 questions