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 buggyObject = {
callAgain: function() {
var ref = this;
var val = setTimeout(function() {
ref.callAgain();
}, 1000);
}
}
buggyObject.callAgain();
buggyObject = null;
Can someone explain the issue in more detail here? I might be missing some subtleties here.
This is definitely a memory leak. However, the memory consumption is so small and cannot be measured. I did some small changes to the source code.
Here is the code:
for (var i = 0; i < 100000; i++) {
var buggyObject = {
callAgain: function() {
var ref = this;
var val = setTimeout(function() {
ref.callAgain();
}, 1000000); //16m
}
}
buggyObject.callAgain();
buggyObject = null;
}
My experiment:
I ran the code in Chrome Version 34.0.1847.116 m and captured memory changes using Developer Tools\Timeline.
As we can see in the picture, around 32 MB of memory has been consumed for running this code and after a while it's been decreased to about 30 MB and stayed unchanged (see #1).
After several garbage collecting attempts by Chrome (see #2) and one manual forced garbage collection by me (see #3, #4), the memory consumption remains unchanged.
There is no more buggyObject
and there is nothing we can do to release the memory. The only possible way is to close the browser.
What causes this?
The main reason for this behavior is the timer. Timer callback and its tied object, buggyObject will not be released until the timeout happens. In our case timer resets itself and runs forever and therefore its memory space will never be collected even if there is no reference to the original object.
There is another question that describes how setTimeout() looks like it has memory leaks, but in reality does not.
However, I think what the author is trying to say is that since buggyObject
creates a setTimeout which calls itself, even if you change buggyObject to equal null
(saying you are done with the object and it can be cleaned up), the object won't be garbage collected because there is still a reference to it in the setTimeout(). This is technically a memory leak because there is no longer any direct reference to the setTimeout function so that you could clear it later (kind of a zombie timeout if you will).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With