这是一个简单的问题,但我找不到任何解决它的人。
使用chrome,通过localhost运行程序。 如果我有一个while循环永不破坏条件,则它将导致页面冻结,没有错误,并且我什至无法关闭chrome上的标签。
如果我有一个递归函数,它会无限调用自己。最大调用堆栈错误将被抛出。
为什么while循环中没有故障保险?当while循环无限期运行时,如何避免页面冻结? (除了正确编写while循环之外)
答案 0 :(得分:1)
您所说的故障安全功能是Safari之外所有实现中都缺少的功能,而Safari已实现tail call optimization的ES2016 JavaScript要求。在野生动物园中,您不会发现这些区别:
while (true) {
// code
}
(function loop () {
// code
loop()
})();
没有堆栈溢出,并且浏览器将永久冻结。原因是,除非您使用worker,否则JS是单线程的,并且转弯队列中不会执行其他JS代码。例如。
setTimeout(function(){ alert("This will never happen!"); }, 0);
(function loop () {
loop()
})();
您不应编写不会终止的while循环。如果您犯了一个错误,我建议您在一段时间内创建一个断点,以检查它为什么不终止。或者,如果您认为有问题,可以这样做:
// TODO: remove debug limit
let limit = 100000; // limit
while (true)) {
if(!limit--) {
console.log('limit exceeded');
break; // set breakpoint here in debugger
}
}
背面是解决问题后需要将其删除。我的IDE抱怨该TODO,因此它将永远不会进入git。您可以对尾部调用执行相同的操作:
// TODO: remove debug limit
let limit = 100000; // limit
(function loop () {
// code
if(!limit--) {
console.log('limit exceeded');
return; // set breakpoint here in debugger
}
if (true) loop(); // might have another expression than true
})();
答案 1 :(得分:0)
答案是使用Chrome并保持DevTools打开。
之所以没有针对无限循环的防护措施,以至于引发无限循环异常的原因是性能。观察检查与不检查之间的差异。
(function(){"use strict";
var i=0, performance_now = performance.now.bind(performance);
var end = performance_now()+200;
while (performance_now() < end) i=i+1|0;
console.log('Ops/sec with checking: ' + Math.round(i / 200 * 1000));
var k = 0;
i = i<<7;
var startTime = performance_now();
while (k < i) void (k=k+1|0);
var endTime = performance_now();
console.log('Ops/sec -- unchecked: ' + Math.round(i / (endTime - startTime) * 1000));
})();
没有与计时器相关的防护措施的版本快300倍。尽管这有点夸张,因为大多数计算时间都花在循环内部而不是外围,但这应该可以使性能达到目的。
关于绕过递归函数中堆栈的限制,请参阅我自己的DeferStackJS库,该库使用堆栈蹦床。
答案 2 :(得分:0)
为什么没有故障保护?
您是安全的。
虽然确实不可能使计算机检测并拦截每个可能的无限循环或无限递归,但计算机可以为之实际执行许多示例(可能是您实际上编写的大多数示例)。
但是,要达到什么目的?
语言规范通常不需要这样做。实现通常不尝试这样做。因为他们不需要。
您测试了代码,发现它的行为不正确。因此,您可以修复它。
这实际上就是所有需要发生的事情。无需复杂的算法即可在25%的时间里为您完成这项工作,而需要大量的计算工作。
您只需修复代码即可。
除了正确编写while循环之外
是的,这就是解决方案。
答案 3 :(得分:-2)
这引起了人们的注意,因为实际上可能无法确定while循环是否将永远确定地运行。
在可计算性理论中,停顿问题是 根据任意计算机程序的描述确定 输入,表明程序是否将完成运行(即停止)或 继续永远运行。
Alan Turing在1936年证明了一种通用算法可以解决 所有可能的程序输入对的停止问题都不存在。
https://en.wikipedia.org/wiki/Halting_problem
您可以单击右上角的三个点,然后选择
更多工具>任务管理器>强制关闭标签