5.1.18 · D4 · HinglishC Programming

ExercisesCommon memory errors — null dereference, buffer overflow, use-after-free, double free, memory leak

2,177 words10 min read↑ Read in English

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.

Figure — Common memory errors — null dereference, buffer overflow, use-after-free, double free, memory leak

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 freefree(p) ek hi address pe do baar call hoti hai; doosri call allocator ki free-list corrupt kar deti hai. (b) Memory leakq 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 dereferencer 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 malloc ke NULL return karne se bachata hai.
  • Fix 2: ka array valid indices rakhta hai. p[3] end ke baad ek step hai (overflow).
  • Fix 3: p = NULL set karna doosre free(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 hai

snprintf 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; a uska address rakhta hai. Legal.
  • (2) Us block mein 100 likhta hai. Legal.
  • (3) b usi address ki copy hai — do sticky notes, ek locker. Legal (aliasing).
  • (4) Block allocator ko wapas karta hai. a ab dangling hai; lekin b bhi dangling hai, kyunki yeh usi freed address ko naam deta hai.
  • (5) b ke through use-after-free. (4) ke baad a = NULL set karna tumhe nahi bachayega — b abhi 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.

  1. *p jahan malloc ne NULL return kiya.
  2. int a[5] mein a[5] likhna.
  3. free(p) ke baad *p padhna.
  4. free(p); free(p);.
  5. p = malloc(...) ek live pointer overwrite karta hai.
Recall Solution 4.2
  1. Null deref → Check malloc.
  2. Overflow → Bounds (indices ).
  3. Use-after-free → Null-after-free (baad mein *p ek detectable null deref ban jaata hai).
  4. Double free → Free once (plus Null-after-free 2nd free(NULL) ko no-op banata hai).
  5. 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 hua
Recall Solution 5.2
  • (2) p[8] ek 8-byte block mein index 8 hai (valid ) → Invalid write (heap-buffer-overflow).
  • (4) free(p) ke baad p[0] padhna → Invalid read (heap-use-after-free).
  • (5) already-freed block ko phir free karna → Invalid free / double free.
  • (6) q ka 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:

Exercise 3.2 mein leaked bytes
30 bytes (unreachable 30-byte block).
"hello" copy karne ke liye correct allocation size
6 bytes ().
64 B/call pe 1,000,000 bytes leak karne ke liye requests
15,625.
Kaun sa CONF-B rule reassignment se leak rokta hai
Owner (one owner per block).