5.1.16 · D5 · HinglishC Programming
Question bank — Stack frames — how function calls work at the memory level
5.1.16 · D5· Coding › C Programming › Stack frames — how function calls work at the memory level
Traps se pehle poora idea picture karo: ek downward-growing stack jisme main, add ko call kar raha hai.

True or false — justify
Har answer mein kyun hona chahiye, sirf bare yes/no nahi.
Mainstream CPUs par stack higher memory addresses ki taraf grow karta hai.
False. x86/x64 aur ARM par har
push stack pointer ko decrease karta hai, isliye stack lower addresses ki taraf grow karta hai — stack ka "top" use mein sabse lowest address hai (upar figure mein dekho, jahan SP neeche hai).Har function call ek brand-new stack frame banata hai.
True (ek normal, non-inlined call ke liye). Har call ko locals, saved registers, aur ek return address ke liye apna private scratch region chahiye, isliye har baar ek fresh frame banta hai — yehi reason hai ki recursion har
n ko alag rakhta hai.Same function ke do simultaneously-active calls apne local variables ke liye same storage share karte hain.
False. Har active call ka apna frame hota hai, isliye har ek ke paas har local ki apni copy hoti hai. Recursion mein
fact(3) aur fact(2) ek saath alive hote hain aur do independent n slots hote hain.Jab function return karta hai usi instant stack frame destroy ho jaata hai.
True in effect. "Destroy" ka matlab sirf itna hai ki stack pointer ko wapas move kiya jaata hai taaki woh bytes reusable ho jaayein; kuch erase nahi hota, lekin woh memory ab us call ki nahi rahi aur agli call use overwrite kar sakti hai.
Return address hamesha stack par store hota hai.
False. x86 par
CALL instruction isse stack par push karta hai, lekin ARM ke BL (branch-and-link) aur RISC-V ke JAL (jump-and-link) par pehle ye link register (LR) mein jaata hai; stack par tabhi pahunchta hai jab woh function kisi aur ko call kare aur link register spill karna pade.Frame/base pointer (BP) aur stack pointer (SP) hamesha ek hi jagah point karte hain.
False. SP stack ke moving top ko mark karta hai (jab aage ke calls ke liye args push karte hain tab shift hota hai); BP current frame ke andar ek fixed anchor hai taaki locals
[BP-8] jaise constant offsets par rahein — chahe SP move kare.Return par frame cleanup karne ke liye har local variable ko ek ek karke delete karna padta hai.
False. Cleanup SP ko ek single move se wahan le jaana hai jahan woh call se pehle tha — yehi LIFO discipline ka poora point hai aur isliye returns saste hote hain.
Kyunki function lifetimes nested hoti hain, calls ke liye stack naturally sahi structure hai.
True. Agar
f, g ko call kare, toh g hamesha f se pehle finish hoga, isliye newest frame hamesha pehla marta hai — jo exactly last-in-first-out (LIFO) hai, yehi stack provide karta hai.Function ko pass kiye gaye arguments hamesha stack par rakhe jaate hain.
False. Bahut saari calling conventions speed ke liye pehle kuch arguments registers mein pass karti hain; sirf extra arguments (ya purani conventions mein) stack par spill hote hain.
malloc se mila block function ke local variables ke same region mein rehta hai.
False. Locals stack par rehte hain (return par automatically free);
malloc tumhe heap memory deta hai jo call se zyada time tak rehti hai aur manually free karni padti hai.Spot the error
Kya galat hai aur kyun, ek ya do sentences mein batao.
int *f(void){ int x=5; return &x; } — bug kya hai?
x, f ke frame mein rehta hai, jo logically f ke return karte hi destroy ho jaata hai; return kiya gaya pointer uss memory ki taraf point karta hai jo ab tumhari nahi hai (undefined behaviour). Fix: x ko value se return karo ya malloc use karo."Dangling-pointer program ne 42 print kiya, isliye &local return karna theek hai."
Return ke baad bytes often abhi bhi 42 happen to hold kar sakte hain, lekin ye undefined behaviour hai — agli function call us stack space ko reuse kar leti hai aur value silently change ho jaati hai.
"ARM par, ek leaf function jo kisi ko call nahi karta, usse bhi LR ko stack par push karna zaroori hai."
Ek leaf function koi aur call nahi karta, isliye LR kabhi overwrite nahi hota; woh return address ko link register mein rakh sakta hai aur stack spill bilkul skip kar sakta hai.
"Maine ek local ka address store kiya, wait kiya, aur abhi bhi valid hai kyunki kuch aur nahi chala."
Bina kisi aur call ke bhi, old SP se neeche ka stack region frame jaate hi fair game hai; correctness "abhi tak kuch overwrite nahi kiya" par depend nahi kar sakti.
"Recursion sirf extra math ki wajah se slow hai."
Asli cost ye hai ki har call ek pura naya frame banaati hai; bahut saare pending frames kabhi free nahi hote, issi tarah deep recursion stack overflow cause karta hai.
"Arguments hamesha BP ke neeche hote hain kyunki BP ke neeche sab kuch frame hai."
Downward-growing stack par, locals (BP ke baad push hote hain) lower addresses par hote hain (
BP - offset), lekin arguments aur koi bhi spilled return address BP se pehle push kiye gaye the aur higher addresses par hote hain (BP + offset).Why questions
Sirf fact nahi, reasoning explain karo.
Har prologue/epilogue mein caller ka BP kyun save aur restore karte hain?
BP ek single shared hardware register hai; callee isse apna frame anchor karne ke liye overwrite karta hai, isliye use entry par caller ka BP save karna hoga aur exit par restore karna hoga — warna caller apna frame reference kho dega.
Locals ko SP ki jagah BP ke relative kyun address karte hain?
SP continuously move karta rehta hai (jaise nested call ke liye arguments push karte waqt), isliye SP se offset mid-function change ho jaata; BP poore frame ki life mein fixed rehta hai, har local ko ek constant
[BP - offset] deta hai.CALL instruction ko return address save karne ki zaroorat kyun hai?
Taaki called function ko pata chale ki finish hone ke baad exactly kis instruction par jump karna hai; iske bina, function end hone ke baad control flow apna rasta kabhi nahi dhundh paata.
Deeply nested recursion stack overflow kyun cause karta hai lekin deep loop nahi?
Ek loop har iteration mein ek hi frame reuse karta hai, jabki har recursive call ek naya frame stack karta hai jo tab tak free nahi hota jab tak return na ho, isliye stack region eventually khatam ho jaata hai.
Program ki stack cleanup "sirf SP move karo" ho sakta hai jabki heap cleanup ke liye explicit free kyun chahiye?
Stack lifetimes perfectly nested (LIFO) hain, isliye SP reset karna ek saath uske upar sab kuch free kar deta hai; heap lifetimes arbitrary hain, isliye har block individually release karna padta hai.
Saved return address overwrite karna dangerous kyun hai?
RET blindly wahan jump karta hai jo address wahan store hai, isliye isse corrupt karna (jaise buffer overflow ke zariye) execution ko attacker ke chosen code par redirect kar sakta hai.Edge cases
Mechanism jo boundaries invite karta hai unhe cover karo.
fact(1) (base case) ka frame fact(3) ke relative kya hota hai?
fact(1) sabse gehri aur newest frame hai, isliye LIFO se ye pehle return aur free hoti hai, phir fact(2), phir fact(3) — jis order mein bane uska ulta.Ek function jiske zero local variables aur zero arguments hain — kya uska frame banta hai?
Ise abhi bhi return address ke liye jagah chahiye (aur shayad ek saved BP ke liye bhi), isliye uska kam se kam ek minimal frame hota hai; "locals ke liye N bytes carve karo" step bas
N = 0 use karta hai.fact(3) ke sabse gehre point par, ek saath kitne frames live hote hain?
Teen:
fact(3), fact(2), aur fact(1) sab ek saath paused hain, har ek apna n hold kar raha hai, kyunki koi bhi tab tak finish nahi ho sakta jab tak uske neeche wala return na kare.Agar main khud ek function hai, toh kya uska bhi frame hota hai?
Haan —
main ek ordinary function hai jiska apna frame hai jisme uske locals hain aur ek return address hai jo C runtime startup code ki taraf jaata hai jisne isse call kiya tha.Function ke return hone ke turant baad lekin caller result store karne se pehle stack pointer ki state kya hoti hai?
SP exactly wahan reset ho chuka hai jahan woh arguments place karne ke baad tha (ya fully wapas, convention par depend karta hai), aur return value store hone ka wait karte hue ek register mein baitha hai.
Tail call — return g(x); as the very last action — kya hamesha ek naya frame banata hai?
Zaroori nahi: tail-call optimization ke saath compiler ek naya stack karne ki jagah current frame reuse kar sakta hai, kyunki
g return hone ke baad caller ke paas koi kaam bacha nahi, jo tail recursion ko ek loop mein badal deta hai aur stack overflow avoid karta hai.Kya sab CPUs apna stack neeche ki taraf grow karte hain?
Nahi — neeche ki taraf sirf mainstream convention hai (x86, ARM). Kuch rare architectures (kuch purane ya embedded designs, aur kuch configurable cores) stack ko upar ki taraf higher addresses ki taraf grow karte hain; physics identical hai, sirf
push ki direction flip hoti hai, isliye [BP + offset] aur [BP - offset] ke roles swap ho jaate hain.Kya ek returned value (pointer nahi) safely ek dying frame se local ka data bahar le ja sakta hai?
Haan — value se return karna data ko callee ka frame destroy hone se pehle ek register ya caller ke frame mein copy karta hai, isliye kuch dangle nahi karta; sirf ek local ka address return karna unsafe hai.
Recall Traps ka one-line summary
Stack usually neeche grow karta hai; har call ek fresh frame paata hai jo SP move karke free hota hai; locals SP ki jagah BP se anchor hote hain; return address pehle link register mein reh sakta hai; tail calls ek frame reuse kar sakte hain; aur kabhi bhi kisi cheez ka address mat do jo kisi frame par hai aur marne wali hai.