free actually free?
It returns the block to the heap allocator's free list for reuse — it does not wipe the bytes and does not change your pointer variable.
Recall Why prefer
malloc(n * sizeof(*p)) over malloc(n * sizeof(int))?
sizeof(*p) automatically tracks p's type, so the line stays correct if the type changes — less bug surface.
Recall Give one case where
calloc is strictly better than malloc.
When you need zero-initialized memory (counters/flags); on most implementations it also splits the size into count/size and detects multiplication overflow (though that overflow check is implementation-defined, not standard-mandated).
Recall Feynman: explain to a 12-year-old
Imagine a library. A normal array is like booking a fixed table before you arrive — you must guess how many friends are coming. The heap is the librarian: you walk up and say "I need 5 chairs" right now (malloc). If a chair was left messy you clean it yourself; if you ask the tidy librarian (calloc) they hand you clean chairs. Need more chairs later? realloc finds a bigger spot and carries your stuff over. When you leave, you must return the chairs (free) or nobody else can use them — that's a "leak." And once returned, stop sitting on them (don't use the pointer), or you'll get a stranger's lap!
Dekho, normal array jaise int a[100]; mein tumhe pehle se size pata hona chahiye — yeh "compile time" pe fix ho jaata hai. Lekin real programs mein size aksar runtime pe decide hota hai (user kitna data dega, pata nahi). Iska solution hai dynamic memory: tum OS se heap naam ki jagah se memory maangte ho exactly jitni chahiye. Yeh kaam karte hain chaar functions — malloc, calloc, realloc, free — sab <stdlib.h> mein.
Simple farak yaad rakho: malloc memory deta hai par andar garbage hota hai (clean karna tumhara kaam). calloc wahi karta hai par sab zero se bhar deta hai, aur count aur size ko alag-alag lekar khud multiply karta hai. Ek baat dhyan rakho — log kehte hain "calloc overflow-safe hai," par C standard yeh guarantee nahi karta; zyada-tar real libc (glibc, musl) overflow detect karke NULL de dete hain, par yeh implementation-defined hai, standard ka rule nahi. realloc purane block ko bada/chhota karta hai aur purana data copy karke preserve rakhta hai. free memory ko wapas heap ko de deta hai taaki dusra koi use kar sake.
Sabse important rule: jitne malloc/calloc kiye, utne free karo — warna memory leak ho jaata hai (memory waste, kabhi wapas nahi milti). Aur free(p) ke turant baad p = NULL; likho, warna pointer "dangling" ho jaata hai aur use karna = crash ya silent bug (use-after-free). realloc ke saath hamesha temporary pointer use karo: tmp = realloc(v, ...), fail hone par v safe rehta hai, success pe v = tmp; — direct v = realloc(v,...) likhoge to fail hone par purana block leak ho jaata hai.
Ek aur pro tip: buffer grow karte time capacity double karo (2,4,8,...), ek-ek karke mat badhao — isse total copying ka cost amortized O(n) ho jaata hai, O(n²) nahi. Yeh exam aur interview dono mein poocha jaata hai.