开发者

Javascript memory leak in simple code

开发者 https://www.devze.com 2023-03-16 14:12 出处:网络
I\'m having some kind of memory problem in my javascript code.I\'ve been searching online for memory leak patterns in javascript, but none of the patterns seem to apply to my code.It\'s very simple co

I'm having some kind of memory problem in my javascript code. I've been searching online for memory leak patterns in javascript, but none of the patterns seem to apply to my code. It's very simple code, there are no closures, I don't even have internal functions, all my variables merely hold simple values, like DOM objects or booleans, I don't even define properties in my variables. But yet somehow I manage to leak so much memory that Firefox (3.6.11) freezes and IE tells me I'm running out of memory at line 73, I've marked that line. The functions to which there are references in the DOM tree are toggle, replyForm and replyExpand.

<script type="text/javascript">
function toggle(expandable){
    if(expandable.parentNode.getElementsByTagName("ul")[0].className=="hide"){
        expandable.parentNode.getElementsByTagName("ul")[0].className="show";
        expandable.innerHTML="▼";
    }
    else{
        expandable.parentNode.getElementsByTagName("ul")[0].className="hide";
        expandable.innerHTML="►";
    }
}

var previousSpan;

function replyForm(span,postId,op,commentID){
    if(removeForm(span))
        return;
    previousSpan=span;

    if(span.nextSibling!=null){
        span.parentNode.insertBefore(form(span,postId,op,commentID),span.nextSibling);
    }
    else{
        span.parentNode.appendChild(form(span,postId,op,commentID));
    }
}

function removeForm(span){
    if(previousSpan==null)
        return false;  <-- Out of memory here according to IE
    if(previousSpan.parentNode.getElementsByTagName("form").length!=0)
previousSpan.parentNode.removeChild(span.parentNode.getElementsByTagName("form")[0]);
    var result=(span==previousSpan);
    if(result)
        collapse(previousSpan);
previousSpan=null;
return result;
}

function form(span,postId,op,commentID){
var result=
"<form id=\"commentform\" method=\"post\" action=\"http://innategamer.300mb.us/wp-comments-post.php\">\n"+
"<p>Replying to "+op+":</p>\n"+
"<p><label for=\"author\">Name *</label><input id=\"author\" type=\"text\" aria-required=\"true\" size=\"30\" value=\"\" name=\"author\"></p>\n"+
"<p>Email *<input id=\"email\" type=\"text\" aria-required=\"true\" size=\"30\" value=\"\" name=\"email\"></p>\n"+
"<p>Website<input id=\"url\" type=\"text\" size=\"30\" value=\"\" name=\"url\"></p>\n"+
"<textarea id=\"comment\" aria-required=\"true\" rows=\"8\" cols=\"45\" name=\"comment\"></textarea>\n"+
"<input id=\"submit\" type=\"submit\" value=\"Post Comment\" name=\"submit\">\n"+
"<input id=\"comment_post_ID\" type=\"hidden\" value=\""+postId+"\" name=\"comment_post_ID\">\n"+
"<input id=\"comment_parent\" type=\"hidden\" value=\""+commentID+"\" name=\"comment_parent\">\n"+
"</form>";
    var div=document.createElement('div');
    div.innerHTML=result;
    return div.firstChild;
}

function replyExpand(span){
    if(span.innerHTML.indexOf("▼")!=-1)
        collapse(span);
    else
        expand(span);
}

function collapse(span){
    if(previousSpan==span)
     开发者_JAVA百科   removeForm(span);
    span.innerHTML=span.innerHTML.replace("▼","►");
    while(span.nextSibling!=null){
        span=span.nextSibling;
        if(span.className=="comment-content show");
            span.className="comment-content hide";
    }
}

function expand(span){
    span.innerHTML=span.innerHTML.replace("►","▼");
    while(span.nextSibling!=null){
        span=span.nextSibling;
        if(span.className=="comment-content hide");
            span.className="comment-content show";
    }
}


</script>


I'd imagine it has something to do with the fact that these two functions call each other, and as a far as I can tell, the if statements, once true, will always be true.

function removeForm(span) {
    if (previousSpan == null) return false; < --Out of memory here according to IE
    if (previousSpan.parentNode.getElementsByTagName("form").length != 0)
        previousSpan.parentNode.removeChild(span.parentNode.getElementsByTagName("form")[0]);
    var result = (span == previousSpan);
    if (result) collapse(previousSpan); // <---------------
    previousSpan = null;  //                               |
    return result;        //                               |
}                         //                               |
                          //                               |
function collapse(span) { //                               |
    if (previousSpan == span) removeForm(span); // <--------
    span.innerHTML = span.innerHTML.replace("▼", "►");
    while (span.nextSibling != null) {
        span = span.nextSibling;
        if (span.className == "comment-content show");
        span.className = "comment-content hide";
    }
}

Effectively:

var previousSpan;

function removeForm( span ) {
    // ...
    if( span == previousSpan ) collapse(previousSpan);
    // ...
}

function collapse( span ) {  // <---here span is previousSpan,
       // <-- always true because you're doing if(previousSpan == previousSpan)
    if (previousSpan == span) removeForm(span);   
    // ...
}

// This makes subsequent comparisons in "removeForm()" always true as well,
//    because now it is guaranteed that "span" is the same as "previousSpan"

So once span == previousSpan in removeForm(), you're passing previousSpan to collapse(). The first thing collapse() does is checks to see if what it received is equal to previousSpan, which it always will be since that was the test to send it in the first place.


Looks like you have an infinite loop going on in there.

removeForm calls collapse

collapse calls removeForm


I'm not going to take the time to go over this with a fine tooth comb. But I do see removeForm calls collapse, which sometimes in turn calls removeForm. The first thing I'm suspicious of is that these two functions are somehow calling each other in an infinite recursion pattern.

Please try putting break points at the beginning of one of these functions.

In your debugger, check the size of the call stack each time you hit a this break point. If the call stack expands until the program runs out of memory, then congratulations, you have just posted a real Stack Overflow on StackOverflow!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号