Visual walkthrough — Valgrind — detecting memory errors
5.1.19 · D2· Coding › C Programming › Valgrind — detecting memory errors
Hum kuch bhi assume nahi karte. Agar "heap" ya "pointer" jaisa koi word aaye, hum pehle use draw karte hain.
Step 1 — Ek byte of memory kya hota hai, aur use "access" karne ka matlab kya hai?
KYA. Computer ki memory ek lambi row of numbered boxes hoti hai. Har box exactly ek byte rakhti hai (0 se 255 tak ka number). Har box ka ek address hota hai — row mein uska position number. Bas itna hi hai "memory": ek line mein numbered boxes.
Ek box ko access karna matlab ya to use read karna (andar ka number dekhna) ya write karna (naya number daalna). Ek program yeh kaam har second mein laakhon baar karta hai.
YEH PEHLE KYU DRAW KARTE HAIN. Har Valgrind concept — addressability, validity, leaks — yeh sab in boxes ke baare mein ek rule hai. Agar boxes tumhare dimaag mein concrete nahi hain, toh baaki kuch bhi samajh nahi aayega.
PICTURE. Neeche, gray strip raw memory hai. Hum ek region highlight karte hain jo tumhara program "own" karega jab wo space maangega.
Step 2 — Heap, aur malloc(20) actually kya karta hai
KYA. Heap un boxes ka ek bada pool hai jise tumhara program runtime pe request kar sakta hai. Request hai malloc(20): "please mere liye 20 consecutive boxes reserve kar do." malloc pehle box ka address wapas deta hai — ek pointer. Dekho malloc and free.
YEH TOOL KYU, PLAIN VARIABLE KYU NAHI. Ek plain variable stack pe rehta hai aur jab uska function return karta hai tab disappear ho jaata hai. Jab tumhe aisi memory chahiye jiska size ya lifetime tum run karte waqt decide karo, tab heap se maangna padta hai. Wahi freedom exactly wajah hai ki heap bugs exist karte hain — koi tumhare liye boxes wapas nahi karta.
PICTURE. Bees boxes "not yours" (gray) se "yours" (blue) mein badal jaate hain. Ab unke upar hum do rows of shadow bits draw karna shuru karte hain jo Memcheck secretly rakhta hai.
Step 3 — Access-legality rule (woh ek check jo "Invalid write" ke peeche hai)
KYA. Har read ya write se pehle, Memcheck ek hi yes/no sawaal poochhta hai: kya jo boxes main touch karne wala hoon, sab mark hain?
YEH EXACT RULE KYU. Hardware yeh kabhi nahi poochhta — woh box number 999 pe bhi khushi se likhega. Valgrind ka poora point yahi missing sawaal insert karna hai. Yeh ek decision procedure hai, formula nahi: ek access diya, output OK ya ERROR.
PICTURE. Ek access ek arrow hai jo boxes ki ek run pe land karti hai. Green arrow = uske neeche har box ka hai (allowed). Red arrow = kam se kam ek box ka hai (forbidden → error).
Step 4 — Overflow a[5] = 42 kaise galat jaata hai — dekhte hain
KYA. Humne 20 bytes reserve kiye = 5 ints ke liye jagah (har int 4 boxes hai). Valid indices hain a[0]…a[4]. Code likhta hai a[5].
Index ko address mein is tarah badla jaata hai:
Toh a[5] byte pe baithta hai — reserved 20 ka bilkul pehla box baad. Us box ka hai.
COMPILER KE BAJAYE YEH YAHAN KYU PAKDA JAATA HAI. Compiler sirf types check karta hai, yeh nahi ki index 5 fit hoga ya nahi. CPU kuch bhi check nahi karta. Memcheck ka Step-3 rule pehla aur akeela guard hai: woh size-4 write ko boxes 20–23 pe land karte dekhta hai, sab ke hain, aur fire karta hai.
PICTURE. Write arrow (size 4) blue block se bilkul 4 red boxes bahar jaata hai.
Step 5 — Ek alag galti: undefined value use karna (V-bits)
KYA. Ab ek program jo kabhi apne box se bahar nahi jaata: woh ek int malloc karta hai aur turant if (*p == 0) karta hai. Box hai (tumhara, koi illegal touch nahi) — lekin tumne kabhi likha nahi, isliye hai.
DO BIT-KINDS KI ZAROORAT KYU HAI. "Kya main yahan allowed hoon?" (A) aur "Jo yahan hai, kya woh meaningful hai?" (V) genuinely alag sawaal hain. Garbage padhna legal hai jab tak tum use apne program ki decisions change karne ke liye nahi karte. Toh Memcheck undefined bits ko silently travel karne deta hai — jab tak woh ek decision (ek branch) tak nahi pahunche, jahaan garbage program ko unpredictably behave kara sakti hai. Dekho Undefined Behaviour in C.
PICTURE. Value flow karti hai: copy theek hai (V-bit saath aata hai), lekin if diamond woh jagah hai jahan alarm bajta hai.
Step 6 — free, aur kyun freed boxes quarantined rehte hain
KYA. free(p) Memcheck ko bolti hai ki poore block mein set karo — "ab tum ise touch nahi kar sakte." Importantly boxes ko turant malloc ko wapas nahi kiya jaata; woh ek quarantine freelist mein baithte hain.
QUARANTINE KYU. Agar free boxes ko instantly recycle kar deta, toh agla malloc wahi boxes ke saath wapas de sakta tha — aur unhe padhne wala ek lingering pointer (use-after-free) legal memory pe land karta aur slip through ho jaata. ko thodi der ke liye rakhna crime scene preserve karta hai.
PICTURE. Block blue→red flip karta hai free pe, phir ek "quarantine" holding pen mein wait karta hai; ek stale read arrow ab red pe land karti hai.
Step 7 — Leaks: exit-time pointer hunt
KYA. Jab main return karta hai, Memcheck ek final sweep karta hai: sab still-live pointers (globals, stack, registers) se shuru hokar, woh unhe heap mein follow karta hai aur har block jo reach ho sakta hai use mark karta hai. Koi bhi block jis tak koi nahi pahunch sakta leak hua tha.
COUNTER KI BAJAYE SCAN KYU. Ek block tab leak hota hai jab uski taraf point karne wala aakhri pointer overwrite ho jaata hai — lekin woh moment run karte waqt invisible hota hai. Sirf exit pe Memcheck ek full census le sakta hai ki kaun-ab-bhi-kahaan-point-kar-raha-hai. Yeh ek mark-and-sweep hai, bilkul garbage collector ke reachability pass ki tarah.
PICTURE. Do blocks; ek pointer pehle se doosre pe move hua. Pehle mein koi arrow nahi → unreachable → "definitely lost".
Step 8 — Edge aur degenerate cases (taaki koi scenario tumhe surprise na kare)
KYA/KYU/PICTURE, sab ek figure mein — woh corners jo naive intuition ko todti hain:
malloc(0)— 0 boxes reserve karta hai.mallocek non-NULL pointer return kar sakta hai, lekin koi bhi access through it hai → Invalid. Kuch bhi tumhara nahi.free(NULL)— legal aur kuch nahi karne ke liye defined. Koi error nahi.- Double
free— doosrafreealready-quarantined block pe hit karta hai → "Invalid free / delete". - Off-by-one read (
a[5]read, write nahi) — same box → "Invalid read of size 4". Reads bhi count karte hain. - Undefined value copy karna (
int y = *p;bina branch ke) — abhi koi error nahi; bit simplyymein copy ho jaati hai. Alarm ek decision ka wait karta hai.
Ek-picture summary
Upar sab kuch ek loop hai: har access se pehle, A check karo; V propagate karo; exit pe leaks ke liye sweep karo.
Recall Feynman retelling — poora walkthrough plain words mein
Memory ek lambi row of numbered boxes hai. Jab tum malloc karte ho, boxes ki ek run tumhari ban jaati hai — Memcheck har ek ke upar ek tiny "1" likhta hai ("tum ise touch kar sakte ho") aur ek tiny "undef" ("lekin jab tak fill nahi karte, yeh junk hai"). Jab bhi tumhara program ek box kholta hai, ek invisible guard "1"s check karta hai: agar tumhare haath ke neeche kisi ek box ka "0" ho, toh woh chillaata hai Invalid access — aise woh box 20 pe likhna pakad leta hai jab tum sirf boxes 0–19 ke maalik ho. "Undef" tags values copy karte waqt saath chale jaate hain, aur guard chup rehta hai — jab tak ek junk value ek if tak nahi pahunchti, jahaan woh program ko randomly behave kara sakti hai; tab woh chillaata hai uninitialised value. Jab tum free karte ho, tumhare saare "1"s "0" mein flip ho jaate hain, aur boxes ek holding cell mein lock ho jaate hain taaki unhe dubara use karne wala ek bhoola-bhatka pointer red-handed pakda ja sake. Aakhir mein, jab program khatam hota hai, guard har abhi-bhi-alive pointer ke saath chalke dekhta hai ki kaun se boxes abhi bhi reachable hain; koi bhi block jise koi point nahi kar sakta, peeche chhod diya gaya tha — ek leak. Teen sawaal, hamesha: Allowed? Real? Peeche chhoda?