ত্রুটিRangeError: কল স্ট্যাকের সর্বোচ্চ আকার অতিক্রম করেছে (যাকে নন-ব্রাউজার পরিবেশে “স্ট্যাক ওভারফ্লো”ও বলা হয়) মানে একটি ফাংশন যা নিজেকে বলে (প্রত্যক্ষ বা পরোক্ষভাবে) এতবার যে জাভাস্ক্রিপ্ট কল স্ট্যাকের স্থান ফুরিয়ে যায়। এখানে প্রতিটি কারণ এবং ফিক্স আছে.
📋 Table of Contents
- কেন এটা ঘটে
- কারণ 1: অসীম পুনরাবৃত্তিমূলক ইভেন্ট হ্যান্ডলার
- কারণ 2: JSON.stringify-এ সার্কুলার অবজেক্ট রেফারেন্স
- কারণ 3: পুনরাবৃত্তের সাথে গভীর বস্তুর ক্লোনিং
- কারণ 4: দুর্ঘটনাক্রমে একটি ফাংশনকে উল্লেখ করার পরিবর্তে কল করা
- ফিক্স: পুনরাবৃত্তকে পুনরাবৃত্তিতে রূপান্তর করুন (ট্রাম্পোলিনিং)
- ডিবাগিং স্ট্যাক ওভারফ্লো প্রায়শই জিজ্ঞাসিত প্রশ্ন
- প্রশ্ন: জাভাস্ক্রিপ্টে সর্বোচ্চ কল স্ট্যাকের গভীরতা কত?
- সর্বাধিক কল স্ট্যাকের আকার অতিক্রম করা ত্রুটিগুলি অসীম বা অত্যন্ত গভীর পুনরাবৃত্তি থেকে আসে৷ সমাধান কারণের উপর নির্ভর করে:
কেন এটা ঘটে
প্রতিটি ফাংশন কল কল স্ট্যাকে একটি ফ্রেম যোগ করে। জাভাস্ক্রিপ্ট ইঞ্জিনগুলির একটি সীমিত স্ট্যাকের আকার রয়েছে (ব্রাউজার/নোড সংস্করণের উপর নির্ভর করে ~10,000-15,000 ফ্রেম)। যখন পুনরাবৃত্ত ফাংশনগুলির একটি সঠিক বেস কেস থাকে না, বা যখন দুটি ফাংশন অনির্দিষ্টকালের জন্য একে অপরকে কল করে, স্ট্যাকটি পূরণ করে এবং RangeError ফেলে দেয়।
// Simplest example: missing base case
function factorial(n) {
return n * factorial(n - 1); // never stops — factorial(0) calls factorial(-1) etc.
}
factorial(5); // RangeError: Maximum call stack size exceeded
// Fix: add base case
function factorial(n) {
if (n <= 1) return 1; // base case stops recursion
return n * factorial(n - 1);
}
কারণ 1: অসীম পুনরাবৃত্তিমূলক ইভেন্ট হ্যান্ডলার
// 🐛 Bug: React onChange updates state, triggers re-render, fires onChange again
function SearchInput() {
const [value, setValue] = useState('');
return <input
value={value}
onChange={(e) => {
setValue(e.target.value);
// If something here triggers another state update that causes re-render...
}}
/>;
}
// 🐛 Bug: useEffect calling function that updates state without dependency guards
useEffect(() => {
setData(processData(data)); // updates data → triggers effect → updates data...
}, [data]);
// ✅ Fix: use functional update or conditional guard
useEffect(() => {
if (data.needsProcessing) {
setData(prev => processData(prev)); // functional update avoids dependency
}
}, [data.id]); // depend on stable identifier, not the object
কারণ 2: JSON.stringify-এ সার্কুলার অবজেক্ট রেফারেন্স
// 🐛 Bug: circular reference crashes JSON.stringify
const obj = { name: "test" };
obj.self = obj; // circular reference
JSON.stringify(obj); // TypeError: Converting circular structure to JSON
// ✅ Fix 1: Replace circular references
function stringifySafe(obj) {
const seen = new WeakSet();
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return '[Circular]';
seen.add(value);
}
return value;
});
}
// ✅ Fix 2: Use structuredClone for deep copying (handles circular refs)
const safeCopy = structuredClone(obj); // built-in, available Node 17+ / modern browsers
কারণ 3: পুনরাবৃত্তের সাথে গভীর বস্তুর ক্লোনিং
// 🐛 Bug: naive deep clone fails on deeply nested objects
function deepClone(obj) {
if (typeof obj !== 'object') return obj;
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k, deepClone(v)]) // crashes at ~10k depth
);
}
// ✅ Fix 1: Use structuredClone (built-in, iterative internally)
const clone = structuredClone(deeplyNestedObj);
// ✅ Fix 2: Convert recursion to iteration for very deep objects
function deepCloneIterative(root) {
const stack = [{ source: root, target: Array.isArray(root) ? [] : {} }];
const result = stack[0].target;
const map = new WeakMap([[root, result]]);
while (stack.length) {
const { source, target } = stack.pop();
for (const [key, value] of Object.entries(source)) {
if (typeof value === 'object' && value !== null) {
if (map.has(value)) {
target[key] = map.get(value);
continue;
}
const newTarget = Array.isArray(value) ? [] : {};
map.set(value, newTarget);
target[key] = newTarget;
stack.push({ source: value, target: newTarget });
} else {
target[key] = value;
}
}
}
return result;
}
কারণ 4: দুর্ঘটনাক্রমে একটি ফাংশনকে উল্লেখ করার পরিবর্তে কল করা
// 🐛 Bug: function immediately calls itself
class Timer {
start() {
this.intervalId = setInterval(this.tick(), 1000); // tick() CALLED, not referenced
// this.tick() returns undefined (or calls tick immediately, which schedules tick...)
}
tick() {
console.log('tick');
this.start(); // calls start() which calls tick() again immediately
}
}
// ✅ Fix: pass function reference, not call result
class Timer {
start() {
this.intervalId = setInterval(() => this.tick(), 1000); // reference, not call
}
tick() {
console.log('tick');
}
}
ফিক্স: পুনরাবৃত্তকে পুনরাবৃত্তিতে রূপান্তর করুন (ট্রাম্পোলিনিং)
// For recursive algorithms that process large inputs:
// 🐛 Recursive sum — crashes for large n
function sum(n) {
if (n === 0) return 0;
return n + sum(n - 1); // crashes for n > ~10,000
}
// ✅ Iterative solution
function sumIterative(n) {
let total = 0;
for (let i = n; i > 0; i--) {
total += i;
}
return total;
}
// ✅ Trampolining (for complex recursive algorithms that are hard to iterate directly)
function trampoline(fn) {
return function trampolined(...args) {
let result = fn(...args);
while (typeof result === 'function') {
result = result();
}
return result;
};
}
const sumTrampoline = trampoline(function sum(n, acc = 0) {
if (n === 0) return acc;
return () => sum(n - 1, acc + n); // returns a thunk instead of recursing
});
sumTrampoline(100000); // works fine
ডিবাগিং স্ট্যাক ওভারফ্লো প্রায়শই জিজ্ঞাসিত প্রশ্ন
// The error stack trace shows the recursive call
// RangeError: Maximum call stack size exceeded
// at factorial (/app/math.js:2:10)
// at factorial (/app/math.js:2:10) ← same line repeated = infinite recursion
// at factorial (/app/math.js:2:10)
// ...
// Step 1: Look for the repeated line in the stack trace
// Step 2: Add console.log with a counter to see how deep it goes
let callCount = 0;
function myFunction(data) {
callCount++;
if (callCount > 1000) {
console.trace('Deep recursion detected at:', callCount);
throw new Error('Stack overflow prevention');
}
// ...
}
// Step 3: Check for circular dependencies
function detectCircular(obj, path = '', visited = new WeakSet()) {
if (typeof obj !== 'object' || obj === null) return;
if (visited.has(obj)) { console.log('Circular at:', path); return; }
visited.add(obj);
for (const [key, val] of Object.entries(obj)) {
detectCircular(val, `${path}.${key}`, visited);
}
}
প্রশ্ন: জাভাস্ক্রিপ্টে সর্বোচ্চ কল স্ট্যাকের গভীরতা কত?
উত্তর: Chrome/Node.js-এ ~10,000-15,000 ফ্রেম; ফায়ারফক্সে ~5,000-10,000; ইঞ্জিন সংস্করণ এবং ফ্রেমের আকার দ্বারা পরিবর্তিত হয়। সংস্করণগুলির মধ্যে সঠিক সংখ্যাগুলি পরিবর্তিত হয়।
প্রশ্নঃ আমি কি কল স্ট্যাকের আকার বাড়াতে পারি?
A: Node.js-এ:
(কেবিতে আকার)। ব্রাউজারে: সম্ভব নয়। আরও ভাল সমাধান: সীমা বাড়ানোর পরিবর্তে পুনরাবৃত্তি ঠিক করুন।node --stack-size=65536 app.jsপ্রশ্ন: একটি স্ট্যাক ওভারফ্লো এবং মেমরি আউট গাদা মধ্যে পার্থক্য কি?
উত্তর: স্ট্যাক ওভারফ্লো (রেঞ্জের ত্রুটি) = অনেকগুলি ফাংশন কল ফ্রেম। হিপ আউট মেমরি (মারাত্মক ERROR) = অনেকগুলি বস্তু বরাদ্দ করা হয়েছে। স্ট্যাক ওভারফ্লো গভীর পুনরাবৃত্তি থেকে হয়; হিপ ত্রুটিগুলি অত্যধিক ডেটা বরাদ্দ করা থেকে হয়৷
প্রশ্ন: 2026 সালে আমি কীভাবে একটি বস্তুকে নিরাপদে গভীরভাবে ক্লোন করতে পারি?
উঃ ব্যবহার
— সমস্ত আধুনিক ব্রাউজার এবং Node.js 17+ এর মধ্যে তৈরি। এটি বৃত্তাকার রেফারেন্স, তারিখ বস্তু, মানচিত্র, সেট এবং অ্যারেবাফারগুলি সঠিকভাবে পরিচালনা করে। JSON.parse(JSON.stringify(obj)) শুধুমাত্র বৃত্তাকার রেফ ছাড়া সাধারণ JSON-ক্রমিক বস্তুর জন্য ব্যবহার করুন।structuredClone(obj)প্রশ্ন: জাভাস্ক্রিপ্টে কি টেইল কল অপ্টিমাইজেশন উপলব্ধ?
উত্তর: তাত্ত্বিকভাবে হ্যাঁ (ES6 স্পেক TCO অন্তর্ভুক্ত), কিন্তু শুধুমাত্র Safari এটি 2026 সালে সম্পূর্ণরূপে প্রয়োগ করে। V8 (Chrome/Node.js) TCO সরিয়ে দিয়েছে। স্ট্যাকের নিরাপত্তার জন্য TCO-র উপর নির্ভর করবেন না — পরিবর্তে পুনরাবৃত্তিমূলক সমাধান বা ট্রামপোলিং ব্যবহার করুন।
উপসংহার
সর্বাধিক কল স্ট্যাকের আকার অতিক্রম করা ত্রুটিগুলি অসীম বা অত্যন্ত গভীর পুনরাবৃত্তি থেকে আসে৷ সমাধান কারণের উপর নির্ভর করে:
পুনরাবৃত্তি বন্ধ করতে একটি বেস কেস যুক্ত করুন, বড় ইনপুটগুলির জন্য পুনরাবৃত্তিকে পুনরাবৃত্তিতে রূপান্তর করুন, গভীর অনুলিপিগুলির জন্য কাঠামোগত ক্লোন ব্যবহার করুন এবং বৃত্তাকার বস্তুর উল্লেখগুলির জন্য দেখুন. স্ট্যাক ট্রেস সবসময় বারবার লাইন দেখায় যা অসীম পুনরাবৃত্তি ঘটায় — প্রথমে এটি পড়ুন এবং ফিক্স সাধারণত সুস্পষ্ট।. স্ট্যাক ট্রেস সবসময় বারবার লাইন দেখায় যা অসীম পুনরাবৃত্তি ঘটায় — প্রথমে এটি পড়ুন এবং ফিক্স সাধারণত সুস্পষ্ট।
🔗 Share this article
✍️ Leave a Comment