Exercises — Common memory errors — null dereference, buffer overflow, use-after-free, double free, memory leak
5.1.18 · D4· Coding › C Programming › Common memory errors — null dereference, buffer overflow, us
Shuru karne se pehle, ek picture jo har problem mein use hone wali vocabulary dikhati hai. Ek pointer ek sticky note hai jisme locker number likha hai; heap woh lockers ki row hai jo malloc deta hai; free ek locker ko desk ko wapas kar deta hai, bina tumhari sticky note mitaye.

Prerequisites jo tum khuli rakh sakte ho: Pointers in C, malloc and free, Stack vs Heap Memory, Undefined Behaviour, Strings in C and the null terminator, Valgrind and AddressSanitizer.
L1 — Recognition
Exercise 1.1
Har snippet mein memory error ka naam batao (choose from: null dereference, buffer overflow, use-after-free, double free, memory leak).
// (a)
int *p = malloc(sizeof(int));
free(p);
free(p);
// (b)
char *q = malloc(50);
q = malloc(80);
free(q);
// (c)
int *r = NULL;
*r = 5;
// (d)
char buf[4];
strcpy(buf, "data"); // "data" = 4 chars + '\0'Recall Solution 1.1
(a) Double free — free(p) ek hi address pe do baar call hoti hai; doosri call allocator ki free-list corrupt kar deti hai.
(b) Memory leak — q ko doosre malloc se overwrite kar diya gaya, isliye pehle 50-byte block ka ek hi pointer kho gaya. free(q) sirf 80-byte block free karta hai. Leaked bytes: .
(c) Null dereference — r mein NULL (address 0) hai, *r likhne se trap hota hai.
(d) Buffer overflow — "data" ko bytes chahiye lekin buf mein sirf hain. Yeh ant ke baad byte likhta hai (woh \0).
L2 — Application
Exercise 2.1
Ise fix karo taaki koi memory error na ho. Har fix aur uski wajah batao.
int *p = malloc(sizeof(int) * 3);
p[3] = 9;
printf("%d\n", *p);
free(p);
free(p);Recall Solution 2.1
Teen bugs hain. Corrected version:
int *p = malloc(sizeof(int) * 3);
if (p == NULL) return 1; // fix 1: malloc check → no null deref
p[2] = 9; // fix 2: valid indices 0..2, p[3] nahi
printf("%d\n", *p);
free(p);
p = NULL; // fix 3: null-after-free
free(p); // ab free(NULL) → guaranteed no-op- Fix 1
mallockeNULLreturn karne se bachata hai. - Fix 2: ka array valid indices rakhta hai.
p[3]end ke baad ek step hai (overflow). - Fix 3:
p = NULLset karna doosrefree(p)ko safe no-op banata hai, double free khatam.
Exercise 2.2
Size-bounded copy use karke safely rewrite karo. src kisi bhi length ka ho sakta hai.
char dst[16];
char *src = get_user_input(); // could be 100 chars
strcpy(dst, src);Recall Solution 2.2
char dst[16];
char *src = get_user_input();
snprintf(dst, sizeof dst, "%s", src); // at most 15 chars + '\0' copy karta haisnprintf at most sizeof dst - 1 = 15 characters likhta hai aur hamesha \0 add karta hai, isliye yeh kabhi exceed nahi kar sakta. Invariant ab function khud enforce karta hai.
L3 — Analysis
Exercise 3.1
Is program ko trace karo. Har numbered line ke liye batao memory mein kya hota hai aur kya yeh legal hai.
int *a = malloc(sizeof(int)); // (1)
*a = 100; // (2)
int *b = a; // (3)
free(a); // (4)
printf("%d\n", *b); // (5)Recall Solution 3.1
- (1) Heap pe 4-byte block allocate hota hai;
auska address rakhta hai. Legal. - (2) Us block mein
100likhta hai. Legal. - (3)
busi address ki copy hai — do sticky notes, ek locker. Legal (aliasing). - (4) Block allocator ko wapas karta hai.
aab dangling hai; lekinbbhi dangling hai, kyunki yeh usi freed address ko naam deta hai. - (5)
bke through use-after-free. (4) ke baada = NULLset karna tumhe nahi bachayega —babhi bhi purana address rakhta hai. Isliye "one owner per block" matter karta hai.
Key insight: jis pointer ko tumne free kiya usse null karna uske aliases ko null nahi karta.
Exercise 3.2
Is program ke liye allocations ki count , distinct live blocks ke frees , aur leaked bytes compute karo.
char *x = malloc(30);
char *y = malloc(40);
x = malloc(50); // x ko reassign karta hai
free(y);
free(x);Recall Solution 3.2
Blocks banaye gaye: -byte, -byte, -byte .
x = malloc(50)ne -byte block ka pointer overwrite kar diya → woh block ab unreachable hai.free(y)-byte block free karta hai.free(x)-byte block free karta hai. Toh distinct live blocks freed.- Kyunki (), -byte block ka leak hai. Leaked bytes .
L4 — Synthesis
Exercise 4.1
Yeh function ek string ko heap pe duplicate karne ka kaam karta hai. Isme do distinct bugs hain. Dono dhundho aur fully correct version likho.
char *mydup(const char *s) {
char *out = malloc(strlen(s)); // (A)
strcpy(out, s); // (B)
return out;
}Recall Solution 4.1
Bug 1 (line A): strlen(s) bytes allocate karta hai lekin copy ke liye strlen(s) + 1 chahiye \0 ke liye. Line B phir 1 byte overflow karta hai.
Bug 2 (lines A–B): malloc kabhi check nahi hota; agar yeh NULL return kare, strcpy ek null dereference hai.
Corrected:
char *mydup(const char *s) {
char *out = malloc(strlen(s) + 1); // +1 for '\0'
if (out == NULL) return NULL; // malloc check
strcpy(out, s); // ab exactly fit hota hai
return out;
}s = "hello" ke liye: strlen = 5, correct allocation bytes.
Exercise 4.2
Parent ka mnemonic CONF-B apply karo (Check, Owner, Null-after-free, Free-once, Bounds). Neeche ke paanch errors mein se har ek ke liye batao kaun sa single CONF-B rule use prevent karta.
*pjahanmallocneNULLreturn kiya.int a[5]meina[5]likhna.free(p)ke baad*ppadhna.free(p); free(p);.p = malloc(...)ek live pointer overwrite karta hai.
Recall Solution 4.2
- Null deref → Check malloc.
- Overflow → Bounds (indices ).
- Use-after-free → Null-after-free (baad mein
*pek detectable null deref ban jaata hai). - Double free → Free once (plus Null-after-free 2nd
free(NULL)ko no-op banata hai). - Leak → One owner per block (ek hi handle overwrite mat karo).
Rule count: 5 mein se 4 bugs Null-after-free + Owner + Check + Bounds se khatam hote hain — exactly parent ka "one discipline kills four of five" claim.
L5 — Mastery
Exercise 5.1
Ek long-running server handle() ko har request pe ek baar call karta hai. Har call ek fixed number of bytes leak karta hai. Neeche ke leak ko dekh ke batao per 1000 requests kitne bytes leak hote hain, aur kitni requests ke baad total leak bytes tak pahunchega (round up karo)?
void handle(void) {
char *log = malloc(64);
char *buf = malloc(256);
// ... dono use karta hai ...
free(buf);
// free(log) bhool gaye;
}Recall Solution 5.1
Har call -byte log block leak karta hai (buf correctly freed hai). Toh leak per call bytes.
- Per requests: bytes.
- bytes tak pahunchne ke liye: requests.
Kyunki yeh request 1 pe kabhi crash nahi karta, aisa leak invisible rehta hai jab tak OOM-killer nahi aa jaata — exactly isliye tools matter karte hain.
Exercise 5.2
Tum is program ko Valgrind and AddressSanitizer ke neeche run karte ho. Har line ke liye woh exact diagnostic batao jo tool report karega (choose: "Invalid write", "Invalid read", "Invalid free / double free", "definitely lost").
char *p = malloc(8); // (1)
p[8] = 'x'; // (2)
free(p); // (3)
char c = p[0]; // (4)
free(p); // (5)
char *q = malloc(16); // (6) — kabhi free nahi huaRecall Solution 5.2
- (2)
p[8]ek 8-byte block mein index 8 hai (valid ) → Invalid write (heap-buffer-overflow). - (4)
free(p)ke baadp[0]padhna → Invalid read (heap-use-after-free). - (5) already-freed block ko phir free karna → Invalid free / double free.
- (6)
qka block kabhi free nahi hua aur uska pointer exit pe kho gaya → definitely lost (leak) of bytes. - Line (3) akela legal hai.
Flagged distinct errors: . Isliye AddressSanitizer/Valgrind mastery-level safety net hai — yeh is page ke har silent UB ko loud banata hai.
Recall Quick self-check tally
Jo bugs tum ab naam le, fix kar, trace kar, prevent kar, aur detect kar sakte ho: null deref, buffer overflow, use-after-free, double free, memory leak. Agar koi bhi level shaky laga, uska [!mistake] box dobara padho — har ek woh single trap hai jo grader us difficulty pe expect karta hai.
Reveal-line drills: