Exercises — Recursion depth limit — stack overflow
1.2.39 · D4· Coding › Introduction to Programming (Python) › Recursion depth limit — stack overflow
Shuru karne se pehle, thoda sa vocabulary jo hum use karenge — sab parent mein bana hua hai, simple words mein dobara bataya gaya hai taaki line one samajh aaye:
Level 1 — Recognition
L1.1 — Missing finish line dhundho
Inme se kaunsa function RecursionError hit karega chahe aap kuch bhi pass karo?
def A(n):
if n == 0: return 0
return A(n - 1)
def B(n):
return B(n + 1)
def C(n):
if n <= 0: return 0
return C(n)Recall Solution
- A — base case
n==0hai AUR har call uski taraf move karti hai (n-1). Non-negativenke liye depth limit ke andar safe hai. (Note: negativen0ko overshoot kar dega aur kabhi nahi rukega — domain assumption matter karta hai.) - B — bilkul base case nahi;
nhamesha badhta hai. Hamesha overflow karta hai. - C — base case hai, lekin
C(n)C(n)ko call karta hai — yeh kabhi base ki taraf move nahi karta. Kisi bhin>0ke liye yeh hamesha overflow karta hai.
Answer: B aur C hamesha overflow karte hain. A nahi karta (non-negative n ke liye depth ≤ limit).
L1.2 — Depth padho
Parent se boom(0) boom(1) call karta hai, phir boom(2), ... Default limit ke saath, kaunsa call number pehla hai jo RecursionError raise karta hai, agar boom(0) pehla frame tha?
Recall Solution
boom(0) frame 1 hai, boom(1) frame 2 hai, ..., boom(k) frame hai.
ka limit frames se tak exist hone deta hai. Frame hai boom(999) — woh call allowed hai. Agla call, boom(1000), frame hoga, jo se zyada hai, isliye boom(1000) woh call hai jo RecursionError raise karta hai.
Key off-by-one: sabse deep call jo succeed hoti hai boom(999) hai (frame ); pehli call jo fail hoti hai boom(1000) hai (frame ).
Level 2 — Application
L2.1 — Frames needed
depth_sum(n) ke liye (base n==0, step n-1, ), depth_sum(4) ke liye sabse deep point par ek saath kitne frames stacked hain? Frames ko us order mein likhiye jisme woh push hote hain.
Recall Solution
Push order (har ek agla ka wait karta hai): depth_sum(4), depth_sum(3), depth_sum(2), depth_sum(1), depth_sum(0).
Yeh frames simultaneously stacked hain. Tab hi jab depth_sum(0) 0 return karta hai frames popping shuru hoti hain (LIFO — last pushed, first popped).
L2.2 — Fit hoga kya?
CPython ka default limit hai. Maano call karne se pehle frames already exist hain (module + REPL bookkeeping). Sabse bada n kya hai jiske liye depth_sum(n) abhi bhi RecursionError ke bina finish hoga?
Recall Solution
Aapki recursion ke liye available depth frames.
depth_sum(n) ko frames chahiye. Require .
Sabse badi safe value: .
L2.3 — Limit set karo
Aapko depth_sum(2000) run karna hai. Total-frame rule ke saath pre-existing frames ke liye, sabse chhoti safe sys.setrecursionlimit value likhiye agar ho.
Recall Solution
Recursion ko chahiye frames: .
Sabse deep point par stack par total frames: .
Isliye aapko limit kam se kam chahiye. sys.setrecursionlimit(2031) minimum hai; practice mein aap isse pad karte (jaise 3000) safety ke liye.
Level 3 — Analysis
L3.1 — Do-branch recursion
def fib(n): # domain: n >= 0
if n < 2: return n
return fib(n - 1) + fib(n - 2)fib khud ko do baar call karta hai. Kya isse maximum recursion depth do guna ho jaati hai? fib(10) ke liye stack sabse deep kitna jaata hai?
Neeche wali figure kya dikhati hai: yeh ek chhote case fib(4) ka call tree rounded boxes mein draw karta hai. Upar fib(4) fib(3) (left) aur fib(2) (right) mein branch karta hai; har ek phir branch karta hai, neeche base cases fib(1) aur fib(0) tak. Coral (pink) path aur green boxes single deepest chain trace karte hain — woh jo hamesha n-1 (left) branch leta hai: fib(4) → fib(3) → fib(2) → fib(1). Grey boxes/edges baaki calls hain. Ek butter-yellow note yaad dilata hai ki left branch puri tarah finish ho jaati hai aur apne frames pop kar leti hai right branch shuru hone se pehle, isliye woh calls kabhi ek saath pile up nahi hote. Point: tree wide hai (bahut calls) lekin sirf sabse deep chain stack depth decide karti hai. Wahi rule fib(10) par apply karo aur maximum depth milti hai.

Recall Solution
Nahi. Depth ek sabse lambi single chain of paused calls hai, calls ki total number nahi. Figure dekho: tree wide hai (bahut calls) lekin deepest path sirf n-1 branch se neeche jaata hai: fib(10) → fib(9) → fib(8) → ... → fib(1).
Woh path ke liye frames push karta hai, isliye frames ke liye hain = maximum frames ek saath stacked.
Total calls bahut zyada hai (fib(10) ke liye calls), lekin sab ek saath live nahi hote — do branches ek ke baad ek run hoti hain, isliye inke beech frames pop ho jaate hain.
L3.2 — Depth vs call count
fib(n) () ke liye, maximum depth (ek saath frames) ke liye formula do aur explain karo kyun yeh total call count nahi hai.
Recall Solution
Max depth hamesha-n-1 path follow karta hai: fib(n) → fib(n-1) → ... → fib(1), depth deta hai ke liye (aur depth ke liye).
Total call count roughly jaisa badhta hai, jahan golden ratio hai — ek fixed constant thoda se bada; isse power tak raise karne se count exponentially balloon karta hai jab badhta hai. Yeh ek time/repetition cost hai, sequentially pay ki jaati hai. Depth ek space cost hai, aur sirf currently paused frames count hote hain. Kyunki left subtree puri tarah finish ho jaati hai (apne frames pop karke) right subtree shuru hone se pehle, woh kabhi coexist nahi karte. Isliye depth = (linearly badhta hai), jabki call count (exponentially badhta hai).
Level 4 — Synthesis
L4.1 — Iteration mein convert karo
depth_sum ko iteratively rewrite karo taaki yeh n = 5_000_000 ke liye bina sys.setrecursionlimit touch kiye kaam kare. depth_sum_iter(100) kya hai?
Recall Solution
def depth_sum_iter(n):
total = 0
while n > 0:
total += n
n -= 1
return totalLoop poore time ek frame reuse karta hai, isliye depth n ki parwah kiye bina rehti hai.
.
L4.2 — Recovery ke saath safe deep call
safe_depth_sum(n) likhiye jo sum return kare agar yeh current limit ke under fit ho, ya None agar overflow ho — crash kiye bina. Confirm karo ki safe_depth_sum(3) 6 return karta hai.
Recall Solution
def depth_sum(n):
if n == 0: return 0
return n + depth_sum(n - 1)
def safe_depth_sum(n):
try:
return depth_sum(n)
except RecursionError:
return NoneRecursionError ek ordinary exception hai (dekho Exceptions and try-except in Python), isliye try/except ise catch karta hai — yeh exactly kyun hai Python ek soft, catchable limit use karta hai segfault ki jagah.
.
Level 5 — Mastery
L5.1 — Poora budget karo
Aapke paas genuinely deep-but-finite recursion hai jise depth chahiye. Measurement dikhata hai pre-existing frames. Har frame stack ka lagbhag bytes use karta hai, aur aapka OS thread ko stack deta hai — yeh bytes hai (ek MiB, mebibyte, exactly bytes hai; decimal MB bytes hoga — hum yahan binary MiB use karte hain). (a) Minimum setrecursionlimit value kya hai? (b) Sabse deep point par stack actually kitne bytes use karega? (c) Kya yeh fit hoga?
Recall Solution
(a) Sabse deep point par alive total frames . Minimum limit . (b) Stack bytes used bytes ( MiB). (c) Available bytes. Kyunki , haan, fit hoga — bytes bachte hain ( MiB). Yeh disciplined tarika hai limit raise karne ka: pehle byte budget compute karo (dekho Memory model — stack vs heap), sirf "million tak crank mat karo."
L5.2 — Python deep tail recursion auto-fix kyun nahi kar sakta?
depth_sum return n + depth_sum(n-1) se khatam hota hai. Kya yeh tail recursion hai? Kya tail-call optimization wala language ise depth par run kar sakta hai? Python mein aapko kya karna chahiye?
Recall Solution
Yeh tail recursion nahi hai: depth_sum(n-1) return hone ke baad, abhi bhi kaam karna hai — addition n + (...). Recursive call last cheez nahi hai jo hoti hai, isliye uska frame alive rehna chahiye result receive karne aur n add karne ke liye. (Dekho Tail recursion and why Python lacks tail-call optimization.)
Even ek true tail-recursive version (accumulator-style, return helper(n-1, acc+n)) Python mein phir bhi overflow karega, kyunki CPython deliberately har frame rakhta hai (clean tracebacks ke liye) — iske paas koi tail-call optimization nahi hai. Isliye Python mein fix dono cases mein same hai: loop mein convert karo, constant depth deta hai. depth_sum_iter(100) = 5050 L4.1 se confirm karta hai ki loop recursion se match karta hai.
L5.3 — Poori cause-chain
Mnemonic "No Base → Frames Race → Stack's out of Space" ko is page ke exact vocabulary se ek clean sentence per link mein reconstruct karo.
Recall Solution
- No Base: missing YA unreachable base case (including ek step jo base se door move karta hai, jaise
depth_sumko negative input) matlab koi recursive call kabhi return nahi hoti. - Frames Race: kyunki koi call return nahi hoti, koi bhi stack frame kabhi pop nahi hota, isliye recursion depth har call ke saath se badhti hai.
- Stack's out of Space: depth recursion limit ( total frames) cross kar leti hai, aur CPython ek catchable
RecursionErrorraise karta hai pehle ki real, fixed-size stack memory khatam ho aur OS segfault kare.
Connections
- Recursion depth limit — stack overflow (index 1.2.39)
- Recursion — base case and recursive case
- Iteration vs Recursion
- Call stack and function frames
- Exceptions and try-except in Python
- Tail recursion and why Python lacks tail-call optimization
- Memory model — stack vs heap