Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do closures create memory leaks?

Tags:

javascript

I was reviewing the slides in this presentation: http://slid.es/gruizdevilla/memory

and on one of the slides, this code is presented with the suggestion that it creates a memory leak:

var a = function () { 
   var smallStr = 'x',
   largeStr = new Array(1000000).join('x'); 

   return function (n) { 
        eval(''); //maintains reference to largeStr
        return smallStr; 
   }; 
}();

Closures can be another source of memory leaks. Understand what references are retained in the closure.

And remember: eval is evil

Can someone explain the issue here?

like image 518
MedicineMan Avatar asked Aug 06 '13 22:08

MedicineMan


People also ask

Does closure cause memory leak?

This process of accessing outer function's variable by an inner function is called a closure. A memory leak occurs when a declared variable is automatically available to the inner nested function and resides in a memory despite it is not referenced in the inner nested function.

How do we avoid memory leaks in closures?

Only capture variables as unowned when you can be sure they will be in memory whenever the closure is run, not just because you don't want to work with an optional self . This will help you prevent memory leaks in Swift closures, leading to better app performance.

How are memory leaks caused?

In general, a Java memory leak happens when an application unintentionally (due to logical errors in code) holds on to object references that are no longer required. These unintentional object references prevent the built-in Java garbage collection mechanism from freeing up the memory consumed by these objects.

What causes memory leak in Web application?

In computer science, a memory leak is a leak of resources when computer software incorrectly manages memory allocation. A memory leak occurs when your web application assigns memory and keeps using it even though it is no longer needed.


2 Answers

If instead of returning a function that does

    eval('');

you returned one that passes its argument

    eval(n);

then someone could call a('largeStr') to get the array, so the JavaScript interpreter cannot garbage collect the array.

Interpreters could realize that

eval('');

is equivalent to

;

but most are not smart enough to do that, so as soon as they see eval they stop allowing GC of closed-over variables as long as the closure is reachable.


The memory leak arises when eval can't effectively access closed-over variables because of the nature of its input:

eval('x' + (n-1));

Since 'x' + (n-1) can't produce a string of JS that references largeStr no input can lead to largeStr being used but it is still pinned in memory.


To see the whole thing in action, play around with

 var f = (function () {
     var a = [,,,,,];
     return function (x) { return eval(x); };
   })();
 alert(f('a.length'));
like image 53
Mike Samuel Avatar answered Oct 03 '22 09:10

Mike Samuel


Okay let's consider what happens here;

var a = (function () { // `a` will be set to the return of this function
   var smallStr = 'x',
   largeStr = new Array(1000000).join('x'); 

   return function (n) { // which is another function; creating a closure
        eval('');
        return smallStr; 
   }; 
}());

The inner function needs to be able to access all variables from the outer function, meaning as long as a reference to it exists, variables from the outer function can't be garbage collected and hence continue consuming memory after it has finished invoking and therefore may result in "memory leaks".

If you're dealing with large data like this and you're finished with it, set it to null

like image 20
Paul S. Avatar answered Oct 03 '22 07:10

Paul S.