2013-03-09 36 views
3

我有一个简单的html/javascript代码,它会创建一些DOM然后删除它们。这个简单的js代码是否有内存泄漏?

<!DOCTYPE html> 
<html> 

    <head lang="en"> 
    <meta charset="utf-8"> 
    <title>Custom Plunker</title> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
    </head> 

    <body> 
    <button onclick="create()"> Create </button> 
    <button onclick="clearContainer()"> Clear </button> 

    <div id="container"></div> 

    </body> 

</html> 

<script> 
    function create() { 
    var c = $("#container"); 
    for(var i = 0;i<10000; i++){ 
    c.append("<li>Hellosd fssd f df sdf f f wef ewf we fwe f wef ewf wef ew few f ewf wf ewf wef </li>"); 
    } 
    } 

    function clearContainer() { 
    var c = $("#container"); 
    c.empty(); 
    } 
</script> 

将会有一个Create按钮和Clear按钮。当我点击创建按钮时,它会将10000 li元素附加到容器div上,当我点击清除按钮时,它将删除它们。

当我在chrome上试用它时,chrome进程的初始内存使用量约为30M,在我多次点击创建按钮后增长到70M,当我点击清除按钮时,它变为50M。它比最初的要多20M。

然后我在IE8上试用它,IE进程初始内存使用量约30M,点击创建按钮一次后增长到100M以上,当我点击清除按钮时,它变为80M。它比最初的多50M。

代码是否有内存泄漏?如何解决它?

+0

你莫名其妙地测量实际数据使用或者是你测量(更可能)的内存保留,这会比实际使用的数据吗? – kainaw 2013-03-09 15:41:44

+0

这里有一个[小提琴](http://jsfiddle.net/3SX59/)看到它在行动。 – insertusernamehere 2013-03-09 15:43:08

回答

7

代码是否有内存泄漏?

不。浏览器只是保留一些内存,以防他们需要重用它,和/或尚未(垃圾)收集不再被引用的对象。因为您已经发布了所有对列表项元素的引用(通过jQuery的empty调用),所以实际上让它们放到浏览器上。

当然,这个答案假设你调用的jQuery函数没有错误导致内存泄漏(尤其是创建li元素的那个)。这可能是一个合理的假设,尽管当然,即使是一个备受尊敬的图书馆也会偶尔出现错误。如果jQuery的一个常用函数(包括元素构造)在给定版本中存在大量内存泄漏,那么考虑到使用该库和参与的团队的人数,可能会在合理的时间内找到,报告并修复它们它。

而且我们也假设有在浏览器的处理的DOM操作导致内存泄漏,这是一个更一定假设没有错误。 (历史上,浏览器]无论味】有过各种各样的问题,内存泄漏,我不认为任何浏览器已经免疫。)

但有在代码没有泄漏,如果你明白了吗。

+0

你确定吗?我测试了OP的代码,并且在每次创建/清除占用的内存后,重要的是大约5到10 MB。 – 2013-03-09 15:46:54

+0

@dystroy:正如你可以只看该代码。 OP没有保留对'li'元素的任何引用,所以OP的代码不是内存泄漏的原因。正如我所说的,它总是可能有一个在jQuery的功能OP呼唤之一,但它更可能只是记忆流失。 – 2013-03-09 15:48:49

+0

在OS X上的Firefox 19“保持”像30MB的第一个*创建/清除*之后每个新一轮之后回落到这一数额。 – insertusernamehere 2013-03-09 15:50:19

4

通过对铬/ Linux的测试,我可靠地重现您泄漏:每个创建/清除循环,使内存5MB增长到10 MB,并将此内存似乎没有被释放。

我注意到,有可能通过稍微改变了明确的功能替换父元素,而不是清空,以避免泄漏:

function clearContainer() { 
    var c = $("#container"); 
    c.remove(); 
    $('<ul id="container"></ul>').appendTo(document.body); 
    } 

有了这个代码,内存回来以后每次在同一水平创建/清除周期。

我不认为这个问题是在jQuery的,但更多的可能是在浏览器的DOM对象作为火狐似乎并不有同样的问题。


编辑

通过自动化测试来进一步推动它,我可以看到内存终于下降(我荣登约150 MB的选项卡,然后可以回来到70 MB)。内存管理的方式显然是贪婪的,但没有真正的内存泄漏。由于内存消耗可以如此不同,我建议你删除的父元素,而不是将其清除,但这不会阻止任何崩溃的内存崩溃似乎不太可能。

+0

+1为努力和变化。 *“...并且这个记忆永远不会被释放。”*你等了多久/你试图看到这个**从未**被释放了什么?你有没有坚持下去,直到有东西坠毁?这是“内存泄漏”的黄金标准(你需要做的事情很多,将它报告为Chromium中的错误)。 (我并不是说这不是一个有趣的结果,只是它不一定是* leak *,而且它显然不是* OP的*代码中的泄漏。) – 2013-03-09 15:57:43

+0

@TJCrowder在我上次测试后内存没有改变,5分钟前。它仍然在136 MB,而我的其他清理功能的内存立即释放。 – 2013-03-09 16:00:31

+0

@消歧:五分钟不是“从不”。再次,你必须推动它,直到有什么东西打破来调用泄漏。否则,你只是不知道GC在内部做了什么。 GC是***复杂***。 – 2013-03-09 16:01:14