递归 - 测试最大堆栈大小时,调用堆栈无法弹出

Recursion - Call stack fails to pop when testing the maximum stack size

本文关键字:堆栈 调用 小时 测试 大堆栈 递归      更新时间:2023-09-26

基本上,当最后一个函数调用返回时,调用堆栈将开始逐个弹出函数调用。但是,当我尝试创建一个接近其最大值大小的调用堆栈时,就会提高uncaught expression

//Code for testing the stack size
var cnt = 0;
function test(){
 //Max stack size is nearer to ~41800
 if(cnt++ == 41763){
  console.log('finished');
  return true;
 }
 return test();
}
test();

所以上面的代码在 chromium 版本 49.0.2623.112 m 中为我抛出了一个异常,如下所示,

未捕获的异常

<真实>

请注意,上述错误中没有消息。我的问题是,

堆栈中的最后一个函数调用已返回true这意味着未超出堆栈大小。 为什么没有返回该堆栈中的其他函数调用?出现此空白异常消息的原因是什么?

这里的问题是

console.log('finished');

这会向调用堆栈添加一些额外的函数,这些函数将超出限制,但通过异常处理,您的代码仍然会被执行。

尝试在没有控制台的情况下运行它.log您会看到您达到了极限并看到 true 或异常。

控制台.log不在javascript规范中,因此行为是未定义的,并且可以从一个版本更改为另一个版本。因此,在您的版本中发生的事情可能不会发生在我们的版本中。

以下是对所发生情况最可能的解释:可以肯定的是,控制台.log会增加堆栈的大小,并且由于是您在返回之前调用的最后一个语句,因此有时会产生Maximum call stack,因为您非常接近限制。最大调用可能发生在控制台.log代码(谁调用其他东西)中,以及此错误将如何处理它,这取决于控制台.log的代码。似乎控制台中的代码.log在发生错误时会引发未捕获的异常。现在,当您使用 try 发现错误时,代码会继续,这就是 true 出现的原因。

这是 jsfiddle 中的一个示例,我在其中覆盖控制台.log结果显示在 HTML 中。您可以通过删除控制台的覆盖代码来玩游戏.log以查看情况如何变化。试试这个,告诉我们结果是否又看起来很奇怪。

值得注意的是,当出现Maximum call stack size exceeded错误时,它也取决于堆栈帧的大小(局部变量)。

注意:在 ECMAScript 6 规范中,如果函数调用是函数中的最后一个操作,它不会进入堆栈,但它会"立即"运行,因此无论您输入什么数字,您的代码都将对所有数字运行而不会出错。