【问题标题】:Can closures (in Javascript) lead to stack fragmentation?闭包(在 Javascript 中)会导致堆栈碎片吗?
【发布时间】:2017-07-12 22:34:01
【问题描述】:

如果一个闭包is一个栈帧是

在函数开始执行时分配,之后不释放 函数返回(好像在堆上分配了一个“堆栈帧” 而不是堆栈!),

这是否意味着堆栈可能会碎片化?

例如,调用 foo(),然后调用 bar()。两者都是闭包。是否有任何情况会使 foo() 的闭包超出范围,或者成为释放的候选对象(在堆栈的情况下释放仅意味着运行时会将堆栈指针移回,释放空间)而 bar() 继续需要堆栈空间?

如果这样的事件反复发生,那么堆栈上就会发生相当于堆碎片的情况,除了堆栈的工作方式,空间会丢失。显然这不会发生。是什么阻止了它的发生?

我对 JavaScript 的上下文特别感兴趣,其中一个人甚至不知道运行代码的机器的粗略概念,但这个问题适用于任何函数式语言。

为了让这个问题变得脚踏实地……

考虑以下代码示例。

outer = function() {
    var foo = function(v) {
        return function() { return v; }
    }

    var bar = function(w) {
        return function() { return w; }
    }

    var f = foo(5);
    var b = bar(7);
    document.writeln(f());
    document.writeln(b());
    document.writeln(f());
    document.writeln(b());
}
outer();

事件序列:调用outer()。它的返回地址保存在堆栈中。 foobarfb 都被提升,因此在调用 outer() 时立即分配到堆栈上。 foo() 使用参数5 调用。与任何局部变量一样,函数foo() 的参数也被分配在堆栈上。函数foo() 也通过堆栈返回一个匿名函数。 bbar 会发生同一对事件。我认为foo() 中的匿名函数是闭包,因为它引用了包含它的范围内的变量,但不要介意语义和闭包是什么。我的问题是:我们怎么知道ffoo()bbar() 处于活动状态时无法释放,从而创建一个空且无法访问的堆栈片段?

【问题讨论】:

标签: javascript


【解决方案1】:

呃。

闭包是一个栈帧……

没有。闭包是一个函数,它引用了查找变量所需的外部作用域对象。

在函数开始执行时分配堆栈帧

是的。堆栈帧将(除了其他东西,如返回地址)包含一个带有声明变量的作用域对象。或者更确切地说,是对它的引用。并非所有变量都分配在堆栈上。

函数返回后不释放

没有。这就是堆栈的全部意义——当函数返回时,堆栈帧被弹出。

(好像作用域是在堆上而不是在栈上分配的!)

不知道为什么说“好像”。闭包引用的范围对象分配在堆上。

【讨论】:

  • 我仍然对了解这些细节非常感兴趣,但我还不能评估你写的内容是否正确(我不想只是打赌你的高分意味着你说的对!)。你能引用任何一本书来讨论堆栈上的内容和堆上的内容,特别是在 Javascript 中,或者在一般的函数式编程中?
  • @Calaf 我不知道或可以推荐任何书籍,我通常在网上获取我的知识。我可以将您指向Wikipedia,其中讨论了实施策略。在你的 JS 引擎中实际使用哪一个取决于引擎的实现,除非有开发者博客,否则通常很难获得详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-28
  • 2013-11-23
  • 1970-01-01
  • 2015-01-12
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
相关资源
最近更新 更多