5.1.15 · D3 · HinglishC Programming

Worked examplesMemory layout — text, data, BSS, heap, stack segments

3,873 words18 min read↑ Read in English

5.1.15 · D3 · Coding › C Programming › Memory layout — text, data, BSS, heap, stack segments

Yeh page ek drill hai: hum har tarah ke questions dhundhte hain jo memory-layout topic pe aa sakte hain aur unme se ek-ek solve karte hain — bilkul completely. Agar aapne abhi tak segments nahi padhe, toh pehle parent padhein: Memory layout — text, data, BSS, heap, stack segments.


The scenario matrix

Har row ko ek case class ke roop mein padhein — ek alag tarah ki situation. Sabse right column us example ka naam hai jo usse nail karta hai.

# Case class Concrete trigger Correct segment Example
1 Global, non-zero init int g = 5; Data Ex 1
2 Global, zero / no init int g; ya int g = 0; BSS Ex 1
3 Function ke andar static static int s = 0; BSS/Data Ex 1
4 Local (auto) variable function mein int x; Stack Ex 1, Ex 3
5 Pointer vs uska target int *p = malloc(...) p→Stack, *p→Heap Ex 2
6 String literal char *s = "hi"; Text (RO) Ex 4
7 Stack pe local array char buf[10]; Stack Ex 4
8 Code / ek function khud void f(void){...} Text (RO) Ex 4b
9 Disk-size degenerate (Data↔BSS) bada array, zero vs non-zero Data file badhata hai / BSS nahi Ex 5
10 Limiting case — collision deep recursion / giant malloc Stack overflow / NULL Ex 6
11 Word problem (real world) server session buffers Heap sizing Ex 7
12 Exam twist — freed memory free ke baad pointer use karna dangling (Heap) Ex 8
13 Growth direction proof addresses numerically compare karna Stack↓, Heap↑ Ex 3

Ab hum har row walk karenge.


Ex 1 — Rows 1–4: har declaration classify karo

Decision procedure — har naam pe apply karo. Teeno yes/no questions order mein poochho:

  1. Kya yeh bina static ke function ka local hai?Stack. (Iska lifetime function call hai.)
  2. Warna iska static storage hai. Kya iska initial value non-zero hai?Data (value disk pe store honi chahiye).
  3. Static storage, value zero ya absent?BSS (sirf ek "reserve & zero" note store hota hai).

Ab grind karo:

Var Q1 local-auto? Q2 non-zero? Segment Yeh step kyun?
a =5 nahi (global) haan Data value 5 ko disk pe survive karna hai
b =0 nahi nahi BSS zero mein koi info nahi → koi disk bytes nahi
c (none) nahi nahi (default 0) BSS uninit global = guaranteed 0
d static=7 nahi (static) haan Data static storage + non-zero
e =3 haan Stack plain local → run return hone pe khatam
f static=0 nahi (static) nahi BSS static "inside function" ko override karta hai: static storage, zero
g static=9 nahi (static) haan Data static storage, non-zero

Verify (consistency kyun hai): exactly do non-zero static cheezein (a, d, g) Data pe jaati hain; do zero static cheezein (b, f) aur uninitialized global (c) BSS pe; sirf plain local e Stack pe. Count: Data = 3, BSS = 3, Stack = 1 — matrix rows 1–4 se match karta hai.


Ex 2 — Row 5: pointer vs woh block jise woh point karta hai

  1. Do objects ko alag karo. Yeh step kyun? malloc do alag cheezein produce karta hai: (i) variable p, ek pointer, aur (ii) 40-byte block jise woh point karega. Unhe kabhi merge mat karo.
  2. p locate karo. p ek plain local hai demo ka bina static ke → question 1 = haan → Stack. Kyun: yeh sirf tab tak rehta hai jab tak demo run kare.
  3. Block locate karo. malloc heap allocator se 40 bytes maangta hai → Heap. Kyun: heap un runtime requests ko hold karta hai jinhe function se zyaada jina chahiye agar aap pointer return karo.
Figure — Memory layout — text, data, BSS, heap, stack segments

Verify (sanity check): agar aap demo se return p; karo, toh returned address abhi bhi valid heap memory pe point karega (block survive karta hai), lekin aap kabhi safely return &(a local) nahi kar sakte — woh address mar jaata hai. Yahi asymmetry woh poori reason hai kyun heap exist karta hai.


Ex 3 — Rows 4 & 13: growth directions real numbers se prove karo

  1. Do stack addresses compare karo. &x = ...a1c8, &y = ...a1c4. Baad mein declare hua y lower address pe baitha hai (). Yeh step kyun? consecutive locals frame build hone ke saath lay out hote hain, toh unka order direction reveal karta hai.
  2. Difference padho. bytes — exactly ek int. Naye locals apne size se neeeche jaate hain → stack grows toward lower addresses.
  3. Do heap addresses compare karo. q = ...880010, p = ...880000. Doosra malloc upar tha (). Kyun: jaise aap aur maangte ho program break upar move hota hai.
  4. Difference padho. bytes. Heap ne ek request ke liye 16 bytes diye jo allocator ne round up kiya. Naye blocks upar jaate hain → heap grows toward higher addresses.
Figure — Memory layout — text, data, BSS, heap, stack segments

Verify (units & magnitude): stack step = 4 bytes = sizeof(int) ✓. Heap addresses () stack addresses () se astronomically chhote hain — confirm karta hai heap-neeche, stack-upar, exactly jaisa layout formula predict karta hai. Do malloc addresses ka difference = .


Ex 4 — Rows 6 & 7: string literal vs local buffer (classic confusion)

  1. Case (1): pointer aur literal. lit ek local pointer hai → Stack. String literal "hello" jise yeh point karta hai ek compile-time constant hai jo read-only Text area mein baki hai. Kyun: literals kabhi change nahi hote, toh compiler ek shared, read-only copy store karta hai — lit ke through likhna undefined behaviour hai.
  2. Case (2): array. buf 6 chars ka local array hai. Saare 6 bytes greet ke stack frame ke andar rehte hain; initializer "hello" runtime pe unme copy hota hai. Kyun: array storage hai, pointer nahi — toh iske bytes wahin hote hain jahan variable hota hai (Stack), aur aap buf[0] modify kar sakte hain.

Verify: sizeof(lit) = 8 (64-bit pe ek pointer); sizeof(buf) = 6 (chheh chars). Alag sizes ⇒ alag objects ⇒ alag ghar. ✓


Ex 4b — Row 8: code khud kahan rehta hai?

  1. greet ki instructions locate karo. Yeh step kyun? ek function koi variable nahi hai; yeh compiler ke banaye machine instructions ka block hai. Woh instructions kahi executable aur unchanging jagah rehni chahiye → Text segment (read-only, shared). Kyun Text aur Data nahi: code run karte waqt kabhi mutate nahi hota, toh isse read-only banana bugs aur viruses dono ko isse rewrite karne se rokta hai.
  2. fp locate karo. fp main ka ek plain local hai → question 1 = haan → Stack. Yeh sirf greet ka address rakhta hai, exactly jaise Ex 2 ka p ek heap address rakhta tha. Kyun: pointer aur woh cheez jise woh point karta hai alag segments mein rehte hain.
  3. Printed address predict karo. Kyunki greet Text mein rehta hai (low addresses, layout ke bottom ke paas), fp ek value print karta hai jo stack addresses jaise 0x7ffe... se kaafi neeche hoti hai — Linux pe usually 0x...55... range mein.

Verify: sizeof(fp) = 8 (64-bit pe function pointer). fp() call karna greet run karta hai — proof ki address valid, executable Text address hai. Address kisi bhi 0x7ffe... stack address se kaafi chhota hai. ✓


Ex 5 — Row 9: disk-size degenerate case (Data ↔ BSS swap)

  1. Version B (sab zero) → BSS. Kyun: har element zero hai, toh file sirf "reserve bytes, unhe zero karo" store karti hai. Disk cost ≈ kuch bytes bookkeeping, essentially payload.
  2. Version A (ek non-zero) → Data. Kyun: array initialized hai, toh compiler ko saare integers reproduce karne mein capable hona chahiye — chahe unme se zero hain, array ki declared value ab "sab zero" nahi rahi, toh poora block Data pe jaata hai aur likh diya jaata hai.
  3. Data payload compute karo. Yeh step kyun? file ko physically integers mein se har ek hold karna hai, aur har int sizeof(int) = 4 bytes occupy karta hai — toh total bytes = (elements ki sankhya) × (bytes per element); count ko element size se multiply karna bas "kitne boxes × har box ka size" hai.

Verify (runtime vs disk): runtime pe dono versions same RAM occupy karte hain (BSS bhi memory mein zeroed hota hai). Saving purely disk pe hai: version B ki file ~4 MB chhoti hai. Units check: bytes × count = bytes ✓. (.)


Ex 6 — Row 10: limiting case (collision → overflow)

  1. (a) Stack budget ÷ frame size. Yeh step kyun? stack pointer exactly ek frame per call sink karta hai, toh jo calls fit honge unki sankhya "total room ÷ room-per-call" hai — same reason jaise aap shelf ki length ko ek book ki thickness se divide karte ho yeh count karne ke liye kitni books fit hongi. bytes. Frame size se divide karo: Toh 4096vi deep call ke aas-paas stack pointer apna guard page cross karta hai → stack overflow (ek segment fault, malloc failure nahi).
  2. (b) Heap budget ÷ block size. Yeh step kyun? har successful malloc(1<<20) free memory ka ek fixed 1 MiB chunk consume karta hai, toh exhaustion se pehle fit hone wali count phir se "total free ÷ per-chunk" hai — (a) jaisi identical logic, bas alag budget aur chunk. Har block = bytes. bytes available ke saath: Block 8192 ke aas-paas, malloc NULL return karta hai — ek alag failure mode (heap exhaustion), jise aap test aur recover kar sakte hain.

Verify: ✓. ✓. Dono divisions exact hain.


Ex 7 — Row 11: real-world word problem

  1. Har user ke real bytes. Yeh step kyun? heap ko aapka data aur allocator ka apna metadata store karna hoga, toh ek user ka true footprint data + overhead hai, sirf 512 nahi jo aapne maanga. Per block: bytes.
  2. Users se multiply karo. Yeh step kyun? har user ek independent heap block hai same size ka, toh total heap = (bytes per block) × (blocks ki sankhya) — Ex 5 jaisa wahi "count × size-of-each" reasoning. bytes.
  3. MiB mein convert karo. Yeh step kyun? question MiB mein poochh raha hai, aur bytes by definition, toh units change karne ke liye hum raw byte total ko se divide karte hain. .

Verify (kaun sa segment & sanity): yeh records Heap pe hain (runtime malloc), Data/BSS pe nahi — unki count compile time pe unknown hai. Pointers jo unhe index karte hain (20,000 pointers ka array) khud bytes kahin aur honge. Peak heap ✓ (16-byte overhead ne hume thoda sa upar push kiya).


Ex 8 — Row 12: exam twist (use-after-free)

  1. p kahan hai? p make ka ek plain local pointer hai → question 1 = haan → Stack, free se pehle bhi aur baad mein bhi. Yeh step kyun: free heap block pe act karta hai, kabhi us stack slot pe nahi jahan address store hai — do objects ko alag karna (jaise Ex 2 mein) exactly wahi hai jo humein batata hai ki p ka ghar untouched hai.
  2. free ne kya change kiya? Isme 4-byte heap block allocator ko wapas kar diya. p ke andar baitha address value unchanged hai, lekin ab yeh aise memory pe point kar raha hai jo aap ab nahi ownatep ek dangling pointer hai. Yeh kyun matter karta hai: allocator un same bytes ko agli malloc ko de sakta hai, toh block ki contents ab aapki nahin.
  3. Kya *p safely read karna safe hai? Nahi. Kyun: dangling pointer se padhna undefined behaviour hai — block mein 42, garbage, ya kisi aur object ka data ho sakta hai, aur khud read bhi fault ho sakti hai. Kuch bhi guaranteed nahi.
  4. Fix. free ke baad turant p = NULL; karo, aur freed block ke liye kabhi return p mat karo (ise return karna caller ko dead memory dereference karne ki invitation hai). Dekho Pointers and dangling pointers.

Verify: *p ki value free se pehle 42 thi; free ke baad iska value undefined hai (guaranteed 42 nahi, kuch bhi guaranteed nahi). Ek hi guaranteed fact hai: p poore time Stack pe raha, aur freed block khud Heap pe tha. ✓


Active recall

Recall Har ek kaun se cell mein jaata hai?
  • Function ke andar static int k = 4; ::: Data (static storage, non-zero)
  • char *s = "abc";"abc" kahan hai? ::: Text (read-only literal)
  • char buf[4] = "abc";buf kahan hai? ::: Stack (local array)
  • Function f ki compiled body ::: Text (read-only code)
  • int *p = malloc(8)p kahan hai, block kahan hai? ::: p Stack pe, block Heap pe
  • free(p) ke baad *p padhna ::: undefined behaviour; p ek dangling Stack pointer hai
  • int big[1000000]; vs = {1} — kya differ karta hai? ::: on-disk file size (BSS vs Data), runtime RAM nahi

Connections

  • malloc, calloc, realloc and free — Ex 2, 6, 7 ke peechhe ka engine.
  • Stack frames and the calling convention — kyun Ex 3 ke locals neeeche sink karte hain.
  • Static and global variables — storage duration — Ex 1 ko power karne wala rule.
  • Pointers and dangling pointers — Ex 8 ka use-after-free.
  • Buffer overflow and stack smashing — Ex 6 ka stack-limit collision.
  • Virtual memory and paging — kyun heap aur stack ke beech middle gap exist karta hai.