【问题标题】:Browser Javascript Stack size limit浏览器 Javascript 堆栈大小限制
【发布时间】:2018-02-08 11:08:41
【问题描述】:

我在 IE 浏览器中遇到了一些客户端 Javascript 堆栈溢出问题, 这发生在第三方库中,该库进行了一些函数调用,出于某种原因,它们偶尔会在 IE 中刹车,只是因为它的堆栈限制较低。

然后我编写了一个小的测试 HTML 来测试某些浏览器的堆栈大小限制,并发现与在 Windows 7 操作系统、8Gb RAM 的笔记本电脑上运行的 FF 7 或 Chrome 14 相比,IE8 实际上具有较小的堆栈限制:

<html>
<body>

<!-- begin Script: -->
<script type="text/javascript">

function doSomething(){

  var i = 3200;
  doSomethingElse(i);

}

function doSomethingElse(i){
  if (i == 0) return -1;
  doSomethingElse(i-1);
}

doSomething(); 

</script>
<!-- END OF PAGE -->

</body>
</html>

当值在 3200 左右时,IE 会引发堆栈溢出,与 IE 相比,Firefox 和 Chrome 可以处理非常深的递归。

我想知道是否有办法将堆栈溢出异常与在 IE 或任何其他浏览器中运行时引发该异常的 Javascript 函数联系起来,以及它是否可以在堆栈中提供带有函数链的堆栈跟踪引发错误的那一刻。

【问题讨论】:

  • 3200 次调用是足够的堆栈空间。 Python 程序员(好吧,那些不热衷于编写递归下降解析器或用递归替换完全简单的循环的人)在 1000 次调用限制下相处得很好。你在做什么?
  • 它没有严格的疑问句,但最后一句“I wonder if there's ...”可以以“Are there”开头并以问号结尾,产生一个相当直接的问题.
  • 感谢您的反馈,我会更好地澄清问题

标签: javascript browser stack limit


【解决方案1】:

使用简单的测试:

var i = 0;
function inc() {
  i++;
  inc();
}
    
try {
  inc();
}
catch(e) {
  // The StackOverflow sandbox adds one frame that is not being counted by this code
  // Incrementing once manually
  i++;
  console.log('Maximum stack size is', i, 'in your current browser');
}

Internet Explorer

  • IE6:1130
  • IE7:2553
  • IE8:1475
  • IE9:20678
  • IE10:20677

Mozilla 火狐

  • 3.6: 3000
  • 4.0: 9015
  • 5.0: 9015
  • 6.0: 9015
  • 7.0: 65533
  • 8b3: 63485
  • 17: 50762
  • 18: 52596
  • 19: 52458
  • 42: 281810
  • 89: 10746
  • 91:26441

谷歌浏览器

  • 14: 26177
  • 15:26168
  • 16:26166
  • 25:25090
  • 47: 20878
  • 51: 41753
  • 93: 13903

Safari

  • 4: 52426
  • 5:65534
  • 9: 63444
  • 14: 45606

Safari iOS

  • 15: 7909

歌剧

  • 10.10: 9999
  • 10.62: 32631
  • 11: 32631
  • 12: 32631
  • 78: 13908

边缘

  • 87: 13970
  • 93: 13903

Yandex

  • 21: 13909

关于您的问题,请使用浏览器的开发人员工具查看堆栈。在 IE 8+ 中,点击 F12,转到“脚本”选项卡,然后单击“开始调试”。当抛出异常时它会中断,你可以看到调用堆栈。您还可以使用 Chrome 的开发者工具,Ctrl+Shift+J

【讨论】:

  • Chrome 也可以使用 F12
  • 通过测试jsfiddle.net/9YMDF/show,Chrome 28 大约为 21000,Firefox 20+ 为 26000..53000,Windows 7 SP1 64 位上的 IE10 大约为 3000。 Opera 12.X 的堆栈深度非常接近 32768。我发现一个不幸的 IE8 安装,堆栈深度等于 276!
  • 您可以将这些结果与the BrowserScope linked here进行比较
  • 这在 Microsoft Edge 上给了我 151102,而在 IE11 上给了我 54375!
  • 我认为这些数字不会映射到浏览器,而是映射到应用程序保留的当前内存。因此,答案千差万别。例如,我刚刚运行了那个测试,我得到了 Chrome 56(带有很多扩展)的 20922,以及相当普通的 Firefox 49 的 8921。使用 absolutely stock 边缘浏览器,我得到16615.
【解决方案2】:

这是特定于浏览器的,不仅是堆栈大小,还有优化,比如尾递归优化等等。我想这里唯一可靠的事情是以一种不会将大量内容放入堆栈或手动测试(深入阅读文档)每个浏览器的方式进行编码。毕竟,当您看到“递归过多”错误或类似错误时,您已经知道您的代码确实有问题。

【讨论】:

  • TCO 真的是用 JavaScript 完成的吗?我读到 ES6 可能会得到支持,但我认为它还没有实现。
  • TCO 现在位于 chrome 中的一个标志后面(正在评估两种不同的实现)。我不知道有任何浏览器默认实现了它。
  • @JanusTroelsen:ES2015(“ES6”)确实需要引擎来做 TCO。 V8 有它,但 V8 团队不认为它“稳定”,所以你必须启用它。 (V8 将他们已经开始的功能分类为“交付”[完成]、“稳定”和“进行中”。总拥有成本仍然“进行中”,但所有三个 V8 代码生成器的基础知识都在那里。我认为他们尚未将其提升为“稳定”,因为他们仍在优化/查找错误/修复错误。更多信息:stackoverflow.com/a/30369729/157247)
  • 目前 safari 是唯一具有适当 TCO 的浏览器
  • “将大量内容放入堆栈”的一个用例是 array1.push(...array2),它比 array1 = array1.concat(array2) 快​​得多,但当 array2 太长时会抛出“超出最大堆栈大小”。见here
猜你喜欢
  • 2016-05-24
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 2018-10-16
  • 2023-04-10
  • 2011-10-02
相关资源
最近更新 更多