Ben*_*aum 13 javascript stack-overflow
我的代码{}在JavaScript中是完全合法的,因为它代表一个块.
但是,我注意到{{...}}在Chrome*中将很多块()嵌套在另一个加注中:
未捕获RangeError:超出最大调用堆栈大小
为什么堆栈溢出发生在这里?
这是一个说明问题的码本(jsfiddle崩溃).
在JSRoom询问时,Zirak发现魔术数字在Chrome 上为3913块,在Firefox 上为2555块.
什么被推到了堆栈?为什么?
(*)我已经检查过,它也发生在IE和Firefox中
更新:我已经检查过并且不可靠IE可以避免堆栈溢出异常.它抛出了两次而不是第三次.如果任何一个读者有IE并且愿意测试它的旧版本(比如IE8和9)并告诉我发生了什么,我真的很感激.
Zir*_*rak 18
首先,ghord是完全正确的.它是由解析器的递归性质引起的,因此请给予他投票的爱.但需要证明,OP希望我将其作为单独的答案发布.
那么,在哪里可以找到它是如何完成的?问一些参与引擎制作的人.所以我去了#jsapi频道irc://irc.mozilla.org并问他们:
< bhackett> zirak: well, with a recursive descent parser all the productions will roughly correspond to a frame on the C stack
< bhackett> zirak: the parser is at js/src/frontent/Parser.cpp
< Waldo> zirak: Parser<ParseHandler>::statement(bool canHaveDirectives) and Parser<ParseHandler>::statements() pretty much
< bhackett> zirak: in this case, the recursion will be Parser::blockStatement ->Parser::statements -> Parser::statement -> Parser::blockStatement
这几乎就是答案.进入mozilla中央存储库并深入挖掘,我们有我们的嫌疑人:
那么,我们拥有的是:
statements哪个调用blockStatement解析块,找到另一个块,调用
statements哪个调用blockStatement解析块,找到另一个块,调用
statements哪个调用blockStatement解析块,找到另一个块,调用
直到堆栈崩溃,我猜这里.
所以我们有Firefox的来源.
从Firefox学习我的课程,我去了v8项目并寻找一个名为的文件parser.果然,它就在那里!
接下来的事情是寻找解析块的时间,所以我天真地搜索statements,到达有希望的ParseStatement.
这是我们的幸运日,一个巨人switch!和第一种情况是我们所关心的,一个电话ParseBlock,另一名有前途!
事实上,内ParseBlock,我们发现一个电话来ParseStatement.所以,要清楚,我们有两个功能:
他们像我们在Firefox中看到的那样互相打电话:
ParseStatement哪个调用ParseBlock解析块,找到另一个块,调用
ParseStatement哪个调用ParseBlock解析块,找到另一个块,调用
ParseStatement哪个调用ParseBlock解析块,找到另一个块,调用
直到kaboom去堆栈.
(很抱歉在最后一次编辑中将其称为闭源!)Safari的js引擎是JavaScriptCore,它驻留在WebKit项目中.找到这些功能与为Chrome找到它们几乎相同,所以让我们跳到有趣的部分:
Parser<LexerType>::parseSourceElementsParser<LexerType>::parseStatementParser<LexerType>::parseBlockStatement我们中间有一个额外的功能,但原理是一样的:
parseSourceElements调用parseStatement哪个调用parseBlockStatement解析块,调用另一个块
parseSourceElements调用parseStatement哪个调用parseBlockStatement解析块,调用另一个块
parseSourceElements调用parseStatement哪个调用parseBlockStatement解析块,调用另一个块
繁荣
...仍将是一个谜,除非他们感到突然想要打开他们的来源,或者一个有进取心的员工与我们分享内部.上面两个伟大的引擎以相同的方式进行,因此我们可以假设其他浏览器也是这样做的.
如果一个浏览器没有崩溃,这是一个有趣的问题,但是这个答案不能希望咳嗽回答.
gho*_*ord 14
简单优雅的递归下降解析器的默认实现,用一种方法解析每个语言语法规则.这些方法以递归方式调用其他方法,因此当您有太多嵌套规则时,它会超出堆栈大小.Chrome和Firefox都使用这种解释器实现.
您会注意到很多"+"虽然与范围无关,但会导致相同的异常:
+ + + + + + + + + ... // same error
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
429 次 |
| 最近记录: |