简体   繁体   English

简单代码中的 Javascript memory 泄漏

[英]Javascript memory leak in simple code

I'm having some kind of memory problem in my javascript code.我的 javascript 代码中有某种 memory 问题。 I've been searching online for memory leak patterns in javascript, but none of the patterns seem to apply to my code.我一直在网上搜索 javascript 中的 memory 泄漏模式,但这些模式似乎都不适用于我的代码。 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.这是非常简单的代码,没有闭包,我什至没有内部函数,我所有的变量都只是保存简单的值,比如 DOM 对象或布尔值,我什至没有在我的变量中定义属性。 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.但是不知何故,我设法泄漏了如此多的 memory 以至于 Firefox (3.6.11) 冻结,IE 告诉我我的 ZCD69B4957F06CD818D7BF3D73980E291Z 标记线用完了。 The functions to which there are references in the DOM tree are toggle, replyForm and replyExpand.在 DOM 树中引用的函数是 toggle、replyForm 和 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)
        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>

Looks like you have an infinite loop going on in there.看起来你在那里有一个无限循环。

removeForm calls collapse removeForm调用collapse

collapse calls removeForm collapse调用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 .但我确实看到removeForm调用collapse ,有时又调用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!如果调用堆栈扩展直到程序用完 memory,那么恭喜,您刚刚在 StackOverflow 上发布了一个真正的 Stack Overflow!

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.我想这与这两个函数相互调用这一事实有关,据我所知, if语句一旦为真,将永远为真。

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() .因此,一旦span == previousSpanremoveForm()中,您将previousSpan传递给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. collapse()做的第一件事是检查它收到的内容是否等于previousSpan ,因为这是首先发送它的测试,所以它总是如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM