5.1.19 · D5 · HinglishC Programming

Question bankValgrind — detecting memory errors

2,151 words10 min read↑ Read in English

5.1.19 · D5 · Coding › C Programming › Valgrind — detecting memory errors

Shuru karne se pehle, teen words yaad rakho (parent ke mnemonic se): Addressability ("kya mujhe yeh byte touch karne ki permission hai?"), Validity ("kya yahan ki value real hai ya malloc ki garbage?"), aur Leak ("kya maine block ka ek maatra pointer kho diya?"). Yahan ka lagbhag har trap asal mein yeh pooch raha hai ki in teeno mein se kaun sa violate ho raha hai — ya koi bhi ho raha hai ya nahi.

Poora page ek hi picture hai. Koi bhi trap touch karne se pehle, yeh map apne dimag mein bitha lo — ek heap block, uske red zones, aur do shadow bits jo har byte ke neeche rehte hain:

Figure — Valgrind — detecting memory errors

Pale-yellow guard bytes ko dekho jo real block ke dono taraf hain: unka A-bit = 0 hamesha hota hai. Yeh ek fact neeche ke "Spot the error" answers ka aadha kaam karta hai — block ke ek byte baad jaana red zone mein jaana hai, aur guard darwaza band kar deta hai.


A/V/L map — jawab dene se pehle yeh padho

Valgrind ka har message jo tum kabhi dekho ge woh exactly teen bins mein aata hai. Yeh parent ke mnemonic ka decision tree hai jo teen letters mein compress hua hai — kisi bhi symptom se uski category tak arrow follow karo:

yes

yes

yes

Valgrind complained. Which bin?

Did you touch a byte you are not allowed to touch?

Did a garbage value change what the program did?

Did a block survive to exit with no live pointer?

A - Addressability

V - Validity

L - Leak

Invalid read or write, use-after-free, double free, past red zone

Conditional jump depends on uninitialised value, syscall on undefined bytes

definitely lost, indirectly lost, possibly lost, still reachable

Ab dekho bits actually change ho rahe hain. Yeh strip ek chhota sa program dikhata hai — malloc, read-before-write, write, free, use-after-free — aur kaise A-bit row aur V-bit row har step pe flip hote hain. "Spot the error" aur "Edge cases" sections ka har trap is film ka ek frame hai:

Figure — Valgrind — detecting memory errors

Left se right trace karo: malloc ke baad block touchable hai (A=1) lekin garbage hai (V=0); write se V=1 ho jaata hai; free ke baad poora block A=0 ho jaata hai aur quarantine mein chala jaata hai — isliye final read pakda jaata hai.

Aur yeh hai jo guard ki report tumhare terminal pe actually dikhti hai, teen bins ke same colors mein taaki ek nazar mein pata chale kaunsa bit fail hua:

Figure — Valgrind — detecting memory errors

True or false — justify karo

Ek clean Valgrind run guarantee karta hai ki tumhara program bug-free hai.
False. Memcheck sirf unhi memory errors ko pakadta hai jo usne actually execute ki paths par dekhe; kisi na-li gayi branch ya na-dekhe input par bug invisible hai, aur logic bugs memory bugs bilkul nahi hain.
Heap block ke start se ek byte pehle padhna theek hai kyunki yeh abhi bhi "tumhari" allocation hai.
False. Block ke thoda neeche ke bytes iske part nahi hain — woh red zone mein hain (figure 1), A-bit 0, isliye yeh "Invalid read ... N bytes before a block" hai. Sirf bytes [a, a+size) tumhare hain.
Memcheck har uninitialised value ka use jis pal padha jaata hai usi pal flag karta hai.
False. Yeh tabhi complain karta hai jab undefined value observable behaviour ko affect kare — ek conditional jump ya syscall argument. Sirf copy karna ya arithmetic-combine karna undefined bits ke saath silent rehta hai; V-bits bas saath chal dete hain.
Leak summary mein still reachable bytes hamesha real leaks hain jo fix karni chahiye.
False. still reachable matlab hai ki exit par block ka pointer abhi bhi exist karta hai (jaise ek global cache jise OSaise bhi reclaim kar leta hai). Yeh aksar harmless hai; definitely lost ko prioritise karo.
-O2 ke saath compile karna Valgrind ko zyada accurate picture deta hai kyunki yeh release build hai.
False. Optimisation us access ko hi reorder, inline, ya eliminate kar sakti hai jo buggy hai aur line info strip kar deti hai. -O0 -g se debug karo; release build ko separately check karo agar zarurat ho.
Jo program exit code 0 return karta hai aur correct output print karta hai usmein koi memory error nahi hai.
False. Heap overflows aur uninitialised reads undefined behaviour hain — "aaj sahi hai" heap layout aur compiler version ka coincidence hai, proof nahi.
Valgrind ke liye tumhara source code special Valgrind instrumentation ke saath recompile karna padta hai.
False. Yeh ordinary binary par kaam karta hai, runtime par ek synthetic CPU par JIT-translate karke. Tum sirf -g add karte ho taaki report source lines ke naam bata sake — yeh optional hai, required nahi.
Same pointer ka double free() V-bit machinery se pakda jaata hai.
False. Yeh addressability/allocator-state issue hai, value ka nahi. Doosra free ek aisi block ko target karta hai jinke A-bits already 0 hain (quarantined), isliye Memcheck "Invalid free() / delete / delete[]" report karta hai.
Agar malloc NULL return kare aur tum usse write karo, Valgrind hamesha invalid write report karega.
False-ish. Address 0 par likhna usually turant segfault karta hai, aur guaranteed diagnosis ek crash hai, necessarily ek neat A-bit message nahi; asli fix hai malloc ka return check karna, jo Valgrind tumhare liye nahi kar sakta.

Spot the error

char *p = malloc(10); strcpy(p, "hello"); free(p); printf("%c", p[0]); — Valgrind kya kehta hai aur kaunsa bit fault mein hai?
Invalid read of size 1 (use-after-free): free ke baad, block quarantine mein hai jahan A-bits = 0 hain (figure 2 ka last frame), isliye p[0] touch karna addressability error hai chahe bytes abhi bhi "hello" dikhte hain.
int *a = malloc(4*sizeof(int)); for(int i=0;i<=4;i++) a[i]=i; — off-by-one kahan hai aur message kya hai?
<= a[4] likhta hai, 4-element block ke ek element baad — seedha figure 1 ke red zone mein: "Invalid write of size 4, 0 bytes after a block of size 16". Byte 16 par A-bit 0 hai.
int x; if (x > 0) foo(); — kya yeh Valgrind error hai, aur woh kya report karega?
Haan: x ek uninitialised stack variable hai, isliye uss par branch karna "Conditional jump or move depends on uninitialised value(s)" deta hai — ek V-bit error. (Note: Memcheck stack values bhi track karta hai, sirf heap nahi.)
char *buf = malloc(100); buf = malloc(200); free(buf); — kaunsa block leak hota hai aur kaise classify hota hai?
Pehla 100-byte block: buf reassign karne ke baad koi pointer uska address hold nahi karta, isliye exit scan usse unreachable paata hai ⇒ "definitely lost". 200-byte block free kiya gaya tha aur theek hai.
free(p); free(p); jahan p ke beech mein null nahi kiya gaya — safe hai ya nahi?
Safe nahi: double free. Doosra call "Invalid free()" hai kyunki block already freed/quarantined hai. Pehle free ke baad p = NULL set karna doosre free(NULL) ko no-op bana deta hai.
int *p = malloc(sizeof(int)); int y = *p + 1; if (y == 5) ... — Valgrind finally kahan complain karta hai?
*p + 1 par nahi, if par. Undefined V-bits addition ke through y mein chale jaate hain, aur sirf conditional jump — jahan garbage control flow change karta hai — report trigger karta hai. --track-origins=yes malloc tak point back karta.

Why questions

Valgrind freed blocks ko freelist par quarantine kyun karta hai instead of immediately allocator ko wapas karne ke?
Taaki A-bits 0 rehein itni der tak ki baad mein koi use-after-free inaccessible memory par pade. Agar block turant reuse ho jaata, toh stale access valid memory par aata aur undetected chala jaata.
Memcheck do alag bit-tracks (A aur V) kyun rakhta hai instead of ek "is this OK" flag ke?
"Kya main ise touch kar sakta hoon?" aur "kya jo yahan hai woh meaningful hai?" — yeh do alag sawal hain. Freed memory untouchable hai lekin uske bytes defined hain; fresh malloc'd memory touchable hai lekin undefined. Ek flag inhe distinguish nahi kar sakta.
--track-origins=yes noticeable speed kyun cost karta hai?
Yeh har undefined value ka birth-place (allocation ya stack frame) record karta hai aur woh provenance operations ke through propagate karta hai — normal V-bit tracking ke upar extra shadow bookkeeping.
Valgrind program ko roughly 10–50× slow kyun karta hai?
Yeh tumhare instructions real CPU par run nahi karta; yeh unhe ek synthetic par JIT-translate karta hai aur har load aur store ko A/V-bit checks mein wrap karta hai. Woh per-access instrumentation hi sab dekhne ki keemat hai.
-g recommended kyun hai chahe Valgrind uske bina bhi run karta hai?
-g debug info embed karta hai taaki report hex addresses ko source file, line, aur variable names tak map kar sake — "Invalid write at 0x4005f2" ko "at main (prog.c:4)" mein badal deta hai. Yeh readability change karta hai, detection nahi.
Memcheck heap overflows kyun pakad sakta hai lekin stack-array overflows zyada nahi?
Yeh heap blocks ke around unaddressable "red-zone" guard bytes lagata hai (figure 1), isliye heap block ke baad jaana 0 A-bit par aata hai. Adjacent stack locals ke beech mein koi red zones nahi hote, isliye ek chhota overflow sirf doosre valid local par aata hai. AddressSanitizer (ASan) us case ke liye stack ko zyada aggressively instrument karta hai.

Edge cases

free(NULL); — error hai ya silently theek hai?
Silently theek. C standard free(NULL) ko no-op define karta hai, aur Valgrind ise waise hi treat karta hai — koi report nahi.
malloc(0) ek pointer return karta hai — kya uss par ek byte likhna theek hai?
Nahi. Zero-size allocation ek 0 accessible bytes ka block deta hai (implementation non-NULL return kar sakta hai), isliye koi bhi write "Invalid write, 0 bytes after a block of size 0" hai.
Program exit par tum sab free karte ho except ek still-in-scope global pointer ke block ke — leak hai ya nahi?
still reachable report hoga, definitely lost nahi: global pointer abhi bhi usmein point karta hai, isliye mark-and-sweep scan ise reachable paata hai. "Lost" leak nahi, chahe technically unfreed hai.
Ek block sirf ek pointer se point kiya jaata hai jo uske middle mein hai, start mein nahi — ise kaise classify kiya jaata hai?
possibly lost: sirf ek interior pointer ise reach karta hai. Valgrind yeh sure nahi ho sakta ki woh address live reference ke roop mein intended hai, isliye woh definitely lost kehne ki bajay hedge karta hai.
Tum block B leak karte ho, lekin B ek maatra pointer tha block C ka — C kaise classify hoga?
indirectly lost: C sirf isliye unreachable hai kyunki lost block B ne uska pointer hold kiya tha. Root leak B hai; B ki leak fix karne se C bhi resolve ho jaayega.
Ek uninitialised value ko syscall ke through file mein write kiya jaata hai — silent hai ya report hoga?
Report hoga. Syscall (jaise write) ko undefined bytes pass karna garbage ka observable use hai, isliye Memcheck "syscall param ... points to uninitialised byte(s)" flag karta hai — same principle jaise conditional-jump case.
Uninitialised memory padhna jis par tum kabhi branch nahi karte aur kabhi output nahi karte — Memcheck ke anusaar bug hai ya nahi?
Memcheck silent rehta hai kyunki value kabhi observable behaviour ko influence nahi karti, lekin principle mein yeh abhi bhi undefined behaviour hai. Yahan silence ka matlab hai "abhi tak harmless", "correct" nahi.

Recall Ek-line self-check

Agar tum kisi bhi Valgrind message ke liye bata sako ki yeh A, V, ya L problem hai (upar ka flowchart walk karo) — aur us boundary case ka naam le sako jisne ise produce kiya — tab tumne yeh bank internalize kar liya hai. Jo bhi in teeno mein fit nahi hota woh Memcheck bug nahi hai; uske liye GDB use karo.