Answered by:
IE appendChild/removeChild memory problem

Question
-
I'm running Vista/ IE7 and when running the leak function the memory in taskmanager goes out of control. I originally thought it might have been a vista/ie7 problem but after some testing it seems random. I've tested it on multiple machines ie6/ie7 xp/vista/2003 and some will have the memory problem where it goes insane and other machines run it just fine with the memory staying close to what the browser had initially.
4 out of 5 vista machines had the problem
1 out of 2 xp ie6 had the problem
1 out of 4 xp ie7 had the problem
0 of 1 server 03 ie6
i tried running windows updates with no help does anyone else have this problem? any ideas?
EDIT: it does occur in firefox as well
<
html> <head> </head> <body> <a href="javascript:leak();">leak</a> </body></
html><
script>var
dialog;function
add(){ dialog = document.createElement('div'); var html = '<div><p>Title</p></div>';dialog.innerHTML = html;
document.body.appendChild(dialog);
dialog.style.marginTop=
'200px';dialog.style.marginLeft=
'200px';}
function
remove(){ document.body.removeChild(dialog);dialog=
null;}
function
leak(){for
(var i=0;i<100000;i++){ add();remove();
} alert('done');}
</
script>
Answers
-
I figured it out. I guess its a psuedo leak it gets cleaned up on page refresh but the problem is i guess the browser for whatever reason keeps a reference to the removed child somewhere so you have to set the innerHTML of the parent to a empty string and it fixes it. no idea why it was behaving differently on different machines tho.
All replies
-
I figured it out. I guess its a psuedo leak it gets cleaned up on page refresh but the problem is i guess the browser for whatever reason keeps a reference to the removed child somewhere so you have to set the innerHTML of the parent to a empty string and it fixes it. no idea why it was behaving differently on different machines tho.
-
function discardElement(element) {
var garbageBin = document.getElementById('IELeakGarbageBin');
if (!garbageBin) {
garbageBin = document.createElement('DIV');
garbageBin.id = 'IELeakGarbageBin';
garbageBin.style.display = 'none';
document.body.appendChild(garbageBin);
}
// move the element to the garbage bin
garbageBin.appendChild(element);
garbageBin.innerHTML = '';
}seems to work for everything except forms
- Proposed as answer by BitMSN Friday, February 19, 2010 5:25 PM
-
I've just run into a very similar leak problem in both IE6 and 7, so it seems we're both finding that IE has some issues with cleaning up after DOM nodes that have been dynamically added then removed.
Here's another way to fix the problem. Additional mem-leak protection code could be added here as well to destroy all on* properties of the node and detach all of the node's event listeners.
Hopefully ie8 will also recurse through its children in the builtin Element.prototype.removeChild : )
function removeChildSafe(el) {
//before deleting el, recursively delete all of its children.
while(el.childNodes.length > 0) {
removeChildSafe(el.childNodes[el.childNodes.length-1]);
}
el.parentNode.removeChild(el);
} -
-
-
Kyle you simply made my day ;-) !!
I just needed to convert a little for my winforms needs, I'll post the results in case it can help someone else:
I First created a GarbageSPAN right after creating my webbrowser istance:
HtmlDocument mydoc = _theWebBrowser.Document;
HtmlElement mynewRow = mydoc.CreateElement("SPAN");
mynewRow.Id = "GarbageSPAN";
mynewRow.Style = "display:none";
mynewRow.InnerHtml = "";
mydoc.Body.AppendChild(mynewRow);
Then I created a method this way for taking out always the first div at the top:
private void TakeOutFirstDiv()
{
HtmlDocument mydoc = _theWebBrowser.Document;
HtmlElement myFirstDIV=null;
HtmlElement myOnlySPAN = null;
HtmlElementCollection myColl = mydoc.GetElementsByTagName("DIV");
foreach (HtmlElement myDiv in myColl)
{
myFirstDIV = myDiv;
break;
}
myOnlySPAN = mydoc.GetElementById("GarbageSPAN");
myOnlySPAN.AppendChild(myFirstDIV);
myOnlySPAN.InnerHtml = "";
}
This one works with IE6, IE7, and IE8 !! Thank you!
Bit.