2016-04-26 122 views
14

基本上调用堆栈将开始弹出功能一个调用一个何时弹出时最后在函数调用返回。但是,当我尝试创建一个更接近其最大尺寸的调用堆栈时,安全问题就会越来越严重。递归 - 调用堆栈失败测试的最大堆栈大小

//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(); 

所以上面的代码抛出一个异常,我在铬版49.0.2623.112米像下面,

Uncaught exception

< true

请不就是上面的错误中没有任何消息。我的问题是,

堆栈中的最后一个函数调用返回了true,这意味着堆栈大小没有被超过。为什么没有返回该堆栈中的其他函数调用?这个空白的异常信息是什么原因?这里

+1

奇怪的是,如果我用较少的迭代运行此代码(即40763),则错误消失,直到页面刷新。 –

+0

在Windows版本为v49.0.2623.87的Chrome上,出现* RangeError:超过最大调用堆栈大小*。并且返回true - 如果不是。 –

+0

也许[this](https://www.safaribooksonline.com/library/view/high-performance-javascript/9781449382308/ch04s03.html)和[this](http://www.2ality.com/2014/04 /call-stack-size.html)有帮助吗? –

回答

8

问题是

console.log('finished'); 

这增加了一些额外的功能调用堆栈,这将让超限,而是通过异常处理代码被执行反正。

试着在没有console.log的情况下运行它,并且你看到你达到了极限并且看到了真实或异常。

+0

如果调用堆栈超过'console.log'调用,那么__Range error__应该被抛出,为什么抛出一个异常而没有消息呢? –

+3

console.log是本机代码,在javascript中没有功能,所以它没有出现javascript堆栈跟踪和异常。 – overflowed

3

console.log不在JavaScript规范中,所以行为是未定义的,并且可以从发行版更改为发行版。所以,在您的版本中发生的事情可能不会发生在我们的身上。

以下是最可能发生的情况的解释:可以肯定的是,console.log会增加堆栈的大小,并且因为是返回之前调用的最后一个语句,所以有时可能会产生一个Maximum call stack,因为您很接近极限。最大的调用可以发生在console.log代码中(调用其他的东西),以及这个错误如何处理它,它取决于console.log的代码。看起来console.log中的代码在发生错误时会引发Uncaught异常。现在,当您尝试使用错误时,代码会继续,这就是真正出现的原因。

下面是jsfiddle中的一个示例,其中我重写了console.log,结果显示在HTML中。您可以通过删除console.log的重写代码来查看事情的变化。试试这个,告诉我们结果是否再次出现奇怪。

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

注意:在ECMAScript 6 spec中,如果函数调用是函数中的最后一个动作,它不会进入堆栈,但会立即运行,因此您的代码将无误地运行,不管你放什么号码。

+0

plus1很好的解释。 –