Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"RangeError: Maximum call stack size exceeded" Why?

If I run

Array.apply(null, new Array(1000000)).map(Math.random);

on Chrome 33, I get

RangeError: Maximum call stack size exceeded

Why?

like image 680
Fabrizio Giordano Avatar asked Mar 02 '14 04:03

Fabrizio Giordano


People also ask

How do I fix error RangeError maximum call stack size exceeded?

The call stack is limited in size, and when it's exceeded, the RangeError is thrown. This can happen when a deeply nested function is called, or when a lot of new variables are created. The most common way to fix this error is to reduce the number of function calls, or to limit the number of variables that are created.

How do I fix error RangeError maximum call stack size exceeded see JavaScript console for details?

The most common source for this error is infinite recursion. You must have a recursive function in your code whose base case is not being met and is, therefore, calling the function again and again until you hit the call stack limit.

What is meant by maximum call stack size exceeded?

It means that somewhere in your code, you are calling a function which in turn calls another function and so forth, until you hit the call stack limit. This is almost always because of a recursive function with a base case that isn't being met.

What does error RangeError maximum call stack size exceeded see JavaScript console for details mean?

The "RangeError: Maximum call stack size exceeded" error occurs when a function is called so many times that the invocations exceed the call stack limit. To solve the error, specify a base case that has to be met to exit the recursion.


5 Answers

Browsers can't handle that many arguments. See this snippet for example:

alert.apply(window, new Array(1000000000)); 

This yields RangeError: Maximum call stack size exceeded which is the same as in your problem.

To solve that, do:

var arr = []; for(var i = 0; i < 1000000; i++){     arr.push(Math.random()); } 
like image 151
Derek 朕會功夫 Avatar answered Sep 17 '22 23:09

Derek 朕會功夫


Here it fails at Array.apply(null, new Array(1000000)) and not the .map call.

All functions arguments must fit on callstack(at least pointers of each argument), so in this they are too many arguments for the callstack.

You need to the understand what is call stack.

Stack is a LIFO data structure, which is like an array that only supports push and pop methods.

Let me explain how it works by a simple example:

function a(var1, var2) {     var3 = 3;     b(5, 6);     c(var1, var2); } function b(var5, var6) {     c(7, 8); } function c(var7, var8) { } 

When here function a is called, it will call b and c. When b and c are called, the local variables of a are not accessible there because of scoping roles of Javascript, but the Javascript engine must remember the local variables and arguments, so it will push them into the callstack. Let's say you are implementing a JavaScript engine with the Javascript language like Narcissus.

We implement the callStack as array:

var callStack = [];

Everytime a function called we push the local variables into the stack:

callStack.push(currentLocalVaraibles);

Once the function call is finished(like in a, we have called b, b is finished executing and we must return to a), we get back the local variables by poping the stack:

currentLocalVaraibles = callStack.pop();

So when in a we want to call c again, push the local variables in the stack. Now as you know, compilers to be efficient define some limits. Here when you are doing Array.apply(null, new Array(1000000)), your currentLocalVariables object will be huge because it will have 1000000 variables inside. Since .apply will pass each of the given array element as an argument to the function. Once pushed to the call stack this will exceed the memory limit of call stack and it will throw that error.

Same error happens on infinite recursion(function a() { a() }) as too many times, stuff has been pushed to the call stack.

Note that I'm not a compiler engineer and this is just a simplified representation of what's going on. It really is more complex than this. Generally what is pushed to callstack is called stack frame which contains the arguments, local variables and the function address.

like image 38
Farid Nouri Neshat Avatar answered Sep 19 '22 23:09

Farid Nouri Neshat


You first need to understand Call Stack. Understanding Call stack will also give you clarity to how "function hierarchy and execution order" works in JavaScript Engine.

The call stack is primarily used for function invocation (call). Since there is only one call stack. Hence, all function(s) execution get pushed and popped one at a time, from top to bottom.

It means the call stack is synchronous. When you enter a function, an entry for that function is pushed onto the Call stack and when you exit from the function, that same entry is popped from the Call Stack. So, basically if everything is running smooth, then at the very beginning and at the end, Call Stack will be found empty.

Here is the illustration of Call Stack: enter image description here

Now, if you provide too many arguments or caught inside any unhandled recursive call. You will encounter

RangeError: Maximum call stack size exceeded

which is quite obvious as explained by others. enter image description here enter image description here

Hope this helps !

like image 23
Om Sao Avatar answered Sep 20 '22 23:09

Om Sao


The answer with for is correct, but if you really want to use functional style avoiding for statement - you can use the following instead of your expression:

Array.from(Array(1000000), () => Math.random());

The Array.from() method creates a new Array instance from an array-like or iterable object. The second argument of this method is a map function to call on every element of the array.

Following the same idea you can rewrite it using ES2015 Spread operator:

[...Array(1000000)].map(() => Math.random())

In both examples you can get an index of the iteration if you need, for example:

[...Array(1000000)].map((_, i) => i + Math.random())

like image 42
Alexander Avatar answered Sep 16 '22 23:09

Alexander


In my experience, this error occurred as a result of a recursive function that never terminates. So I put in a condition for which the recursion must stop executing and return (break out). So by adding the line of code below, I was able to get rid of this error.

if (debtTypesCounter === debtTypesLength) return;

So, you can tweak this idea to suit your condition. Hope this helps?

like image 39
Joshua Gato Avatar answered Sep 18 '22 23:09

Joshua Gato