Closure memory leaks

Mike Samuel mikesamuel at gmail.com
Sun May 22 15:01:50 PDT 2011


2011/5/22 David Bruant <david.bruant at labri.fr>:
> Hi,
>
> After reading an article [1], I've been thinking about scopes in ECMAScript.
> The idea in the article is that a closure keeps a reference to everything in
> its scope. If in turn, one element in the scope keeps a reference to the
> function (like as an event listener for an element), then, it creates a
> circular reference.
>
> Of course, as said in a couple of comments, circular references aren't a
> problem since modern GC (IE8+ and other relevant browsers) aren't
> reference-counting GC.
> But the problem could exist anyway if, for instance a function has in its
> scope an object it doesn't use.
> Example:
> ----
> "use strict";
> function f(){
>     var o = {}; // In g's scope, but unused anyway
>     return function g(){
>                return 1;
>            };
> }
> ----
> I originally thought that a static analysis of the closure could be enough
> to determine whether things in the scope will ever be used or not.
> It turns out it's not the case:
> ----
> "use strict";
> function f(){
>     var o = {a:1};
>     return function(e){ // doesn't strictly use o
>                return eval(e);
>            };
> }
> console.log( f()('o') ); // returns the enclosed o object (at least on FF4)
> ----
> So, this leads to a couple of questions:
> - Is the previous code snippet correct?
> - In which cases can static analysis be enough?

When the name "eval" is not mentioned static analysis can conclude
what needs to be captured by a closure and what doesn't.

If "eval" is aliased, it binds in the global scope.

Static analysis that can prove that a closure mentioning "eval" has a
lifetime that is bounded by the call of the function in which it is
declared can also be ignored.  So if "eval" can't capture
arguments.callee because it's strict, and the function has no name,
and does not escape due to non-eval usage, then variables don't need
to be pinned.

> - Are there other forms of analysis that automatically prevent scope memory
> leaks?
> - Are there good practices people could use to avoid such leaks?
> - Are "let" or "const" of any help here?

Let and const can help in this case:

function outer() {
    function closure(s) {
      return eval(s);
    }

   for (...) {
     let largeObject = ...;
   }

   return closure;
}

if largeObject were declared var, then closure would have access to it
so it would have to be pinned.




> - If they aren't, would it make sense to have an initializer keyword to
> create variables which could NOT be captured by closures? It would avoid
> memory leak, but also would avoid to leak implementation details.



> Thanks,
>
> David
>
> [1] http://atkinson.posterous.com/javascript-closure-memory-leak
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>


More information about the es-discuss mailing list