2016-04-26 118 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很好的解釋。 –