2

I seem to have a memory leak, caused by using the 'new Image()' in a javascript script. If I watch the used physical memory in the windows resource monitor, i get the expected increase in memory used when I load the page because it loads some quite large images using as follows:

var imgObjs = [];

// in for loop i = 0, 1, 2...
imgObjs[i] = new Image();
imgObjs[i].onload = function(event) {
    // image loaded
}
imgObjs[this.img_src].src = this.img_src;

I would have though that when the page is navigated away from this would automatically destroy the references and free up the memory, but this doesn't seem to be the case. Instead, i navigate away and then go back to the page only the find the memory ramp up even more as it loads the images again without ever freeing up the previously allocated memory. I have tried manually removing references by putting code in the unload event to do this but it doesn't seem to make any difference. The variables were all initially declared with 'var':

// allow garbage collection by removing references
$(window).unload(function() {
    for(var i in imgObjs) {
    imgObjs[i] = null;
    delete imgObjs[i];
}
delete imgObjs

// delete other variables that reference the images
});

does anyone have any pointers as to where I'm going wrong here? I thought the problem might be to do with circular references as i have built a list class where each item contains a reference to the previous and next image, but i have deeted these as follows:

delete galleries[i].pictures.Items[j].prev;
delete galleries[i].pictures.Items[j].next;
Grub
  • 844
  • 2
  • 10
  • 21
  • possible duplicate of [Javascript + IMG tags = memory leak. Is there a better way to do this?](http://stackoverflow.com/questions/336348/javascript-img-tags-memory-leak-is-there-a-better-way-to-do-this) – bzlm Sep 25 '11 at 10:33
  • You've asked five questions here on SO and NEVER accepted one as the best answer. Please fix that or people will start ignoring your questions. – jfriend00 Sep 25 '11 at 15:17
  • Didn't realise that was how it worked. I'll do that now. – Grub Sep 26 '11 at 12:05

1 Answers1

10

First off, there is no browser that I know of that leaks when you go to another page just because you have images stored in a JS array.

There are some older browsers that leak if you have circular references between DOM <==> JS where some javascript refers to a DOM element and a custom attribute on the DOM element refers back to the same javacript object, but that does not appear to be what you have here.

So ... I'd be surprised if what you're seeing is actually a leak in going from one page to the next. If you're convinced it is, then create either a plain web page that you can share with us or a jsFiddle that shows the issue and tell us what exact browser you're testing in and exactly how you're measuring the memory usage that determines you have a leak.

For it to truly be a leak, you have to consistently see memory usage go up and and up and up, every time you go to the page over and over again. Just because total memory usage is a little bit higher the second time you go to the page does not mean you have a leak. The browser has some data structures that grow (to a point) with usage like the memory-based cache, the session browsing history, etc... that are not indicative of leaks.

Second off, I don't see anything in the data structures you've shown that are illustrative of the kinds of circular references that are known to cause leaks in older browsers.

Third off, the delete operator is for removing properties from an object. That's all it's for. See these articles: Understanding Delete and MDN Delete for a lot more explanation. So, your cleanup code in the unload handler is not using delete properly. You cannot delete vars or array elements with delete. Though I can't see any reason why this code is necessary, if you were going to have it, it would be like this:

// allow garbage collection by removing references
$(window).unload(function() {
    for (var i = 0; i < imgObjs.length; i++) {
        imgObjs[i] = null;
    }
    imgObjs = null;
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • thanks for your feedback. I had made a custom 'CircularListItem' class which was intended to represent an image carousel that i am making. I hadn't posted the code for that because i didn't know how relavant it would be or if there was just something more fundamental that i was misunderstanding. I think what i will do is go over the articles you have provided and see if I can get a sounder understanding and update this if I work out what is happening. – Grub Sep 26 '11 at 12:14
  • Since posting this i found that setting them to null as you suggested rather than the apparent misuse of 'delete' seemed to keep to allow the browser to free up memory. Before this the memory had increased in clear steps each time the page was refreshed until the point where most of the 4GB of ram i have was full! Thanks for the advice. – Grub Sep 26 '11 at 12:14
  • Totally agree! I think this answer must be included in every JS book! – Timur Gilauri Nov 30 '18 at 06:57