-3

I have this function which I want to loop without stopping the script. But when I use 'console.log' the function stops. If I remove it, the function continues.

How to make this function continue after it has exceeded stack size?

var i = 0;
function computeMaxCallStackSize() {
    try {
        i++;
        console.log(i);
        //some function to execute
        computeMaxCallStackSize();
    } catch (e) {
        //'e' is the error when max stack exceeds
        // setTimeout() is to wait before calling the function
        // if stack size exceeds it recalls the function
        setTimeout(computeMaxCallStackSize(), 0);
    }
}
computeMaxCallStackSize();

Edit: This function will cause a stack overflow and continues.

var a = 1;
var b = 8769; //stack size
func(a);
    function func(a) {
        try {
            console.log(a);
            if(a % b === 0){
                setTimeout( function() {func(a+1); }, 0);
            } else {

                func(a+1);
            }
            
        } catch (e) {
            console.error(e);
            setTimeout( function() {func(a); }, 1);
        }
    }
  • 1
    So... you want to exceed the stack size? You can't, that's what the error is telling you. – Heretic Monkey May 18 '21 at 17:32
  • Don't press "Run code snippet" to reduce the CO2 emission! – astef May 18 '21 at 18:11
  • stack size overflow is a process level operation. You can't interfere with that from a higher order operation. What your trying to do is impossible – Liam May 19 '21 at 12:26
  • WHY are you trying to do this? A stack overflow means your code is broken. Fix it instead of trying to circumvent the problem. – Ian Kemp May 19 '21 at 12:50

3 Answers3

1

If I remove it, the function continues.

No it doesn't, it will finish also, but much later. console.log() taking much more resources cause it needs to render text in console, so it's reaching call stack faster.

You just made infinite loop, that will run till browser will run out of memory.

ulou
  • 5,542
  • 5
  • 37
  • 47
0

I don't see a way to catch stackoverflow in nodejs. From what I know from other ecosystems, it is impossible. See C# catch a stack overflow exception for example. Also see a note about exceptions:

Some exceptions are unrecoverable at the JavaScript layer. Such exceptions will always cause the Node.js process to crash. Examples include assert() checks or abort() calls in the C++ layer.

Process stack is fixed-size, contiguous block of memory, usually not very big (because it's purpose is to make use of process caches). This means that you can't "extend" it on your wish (only at process start). If you can't extend it, why bothering checking it's boundaries every time you do a function call? OS will do the job and crash your process for you!

I know it's not always possible in case of highly-recursive academic algorithms, but from business perpective, you should always unwrap your recursion, especially if it's deep. Even if you think you control it (like, it's only 2000 deep, who cares?), in reality you don't, since usually you don't fully control the caller stack size, and the end-user platform limitations.

BUT!

If you REALLY want to recover your process after stackoverflow, and you're ready for such an adventure (win api, build node from sources, etc.), I will leave this for you.

astef
  • 8,575
  • 4
  • 56
  • 95
0

Your setTimeout is kind of pointless the way it is:

// Current code:
setTimeout(computeMaxCallStackSize(), 0);

// What you really want:
setTimeout(computeMaxCallStackSize, 0);

To answer your question - you don't want to write code which can exceed the stack - that's always an indication of poorly written code. Furthermore, there's not really a way to check the stack size or to check when the stack is "clear" again (for good reason - people would abuse that knowledge to write poor code).

If you need recursion, you almost always build in a "depth" parameter to the function so the function stops after a certain call depth. Something like this:

function someRecursiveFunction(_depth = 0) {
  if(_depth < 100) {
    // do the stuff
    someRecursiveFunction(_depth + 1)
  }
  throw new Error('Oh no, we called this function too many times');
}

If you're just doing this for giggles and really want to see how deep the stack hole goes, I guess you could count the iterations. As mentioned in other comments, the console log is going to take up additional resources - so you might get 1 million iterations without the logging and only 100K with logging. Again, there's no way to ask the JS runtime "how many resources to I have left". The function you are writing is simply a "for fun" experiment and should not be used in real life code.

Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96