Javascript教程:关于内存泄漏问题

2016-02-20 00:44 1 1 收藏

生活已是百般艰难,为何不努力一点。下面图老师就给大家分享Javascript教程:关于内存泄漏问题,希望可以让热爱学习的朋友们体会到设计的小小的乐趣。

【 tulaoshi.com - Web开发 】

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/webkaifa/)

浏览本站的 Javascript教程 栏目内容。

常规循环引用内存泄漏和Closure内存泄漏

要了解javascript的内存泄漏问题,首先要了解的就是javascript的GC原理。

我记得原来在犀牛书《JavaScript: The Definitive Guide》中看到过,IE使用的GC算法是计数器,因此只碰到循环 引用就会造成memory leakage。后来一直觉得和观察到的现象很不一致,直到看到Eric的文章,才明白犀牛书的说法没有说得很明确,估计该书成文后IE升级过算法吧。在IE 6中,对于javascript object内部,jscript使用的是mark-and-sweep算法,而对于javascript object与外部object(包括native object和vbscript object等等)的引用时,IE 6使用的才是计数器的算法。

Eric Lippert在http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx一文中提到IE 6中JScript的GC算法使用的是nongeneration mark-and-sweep。对于javascript对算法的实现缺陷,文章如是说:

"The benefits of this approach are numerous, but the principle benefit is that circular references are not leaked unless the circular reference involves an object not owned by JScript. "

也就是说,IE 6对于纯粹的Script Objects间的Circular References是可以正确处理的,可惜它处理不了的是JScript与Native Object(例如Dom、ActiveX Object)之间的Circular References。

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/webkaifa/)

所以,当我们出现Native对象(例如Dom、ActiveX Object)与Javascript对象间的循环引用时,内存泄露的问题就出现了。当然,这个bug在IE 7中已经被修复了[http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html]。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp 中有个示意图和简单的例子体现了这个问题:

html
head
script language = " JScript "
var myGlobalObject;
function  SetupLeak()  // 产生循环引用,因此会造成内存泄露
{
    //  First set up the script scope to element reference
    myGlobalObject  = document.getElementById("LeakedDiv");
    //  Next set up the element to script scope reference
    document.getElementById(" LeakedDiv ").expandoProperty  = myGlobalObject;
}
function  BreakLeak()  // 解开循环引用,解决内存泄露问题
{
    document.getElementById( " LeakedDiv " ).expandoProperty  = null ;
}
/script
/head
body onload = "SetupLeak()"  onunload = "BreakLeak()"
div id = "LeakedDiv" /div
/body
/html   

上面这个例子,看似很简单就能够解决内存泄露的问题。可惜的是,当我们的代码中的结构复杂了以后,造成循环引用的原因开始变得多样,我们就没法那么容易观察到了,这时候,我们必须对代码进行仔细的检查。

尤其是当碰到Closure,当我们往Native对象(例如Dom对象、ActiveX Object)上绑定事件响应代码时,一个不小心,我们就会制造出Closure Memory Leak。其关键原因,其实和前者是一样的,也是一个跨javascript object和native object的循环引用。只是代码更为隐蔽,这个隐蔽性,是由于javascript的语言特性造成的。但在使用类似内嵌函数的时候,内嵌的函数有拥有一个reference指向外部函数的scope,包括外部函数的参数,因此也就很容易造成一个很隐蔽的循环引用,例如:

DOM_Node.onevent -function_object.[ [ scope ] ] -scope_chain -Activation_object.nodeRef -DOM_Node。

[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp]有个例子极深刻地显示了该隐蔽性:

html
head
script language = "JScript"
function  AttachEvents(element)
{
    //  This structure causes element to ref ClickEventHandler
    //  element有个引用指向函数ClickEventHandler()
    element.attachEvent("onclick", ClickEventHandler);
    function  ClickEventHandler(){
                 //  This closure refs element
                 //  该函数有个引用指向AttachEvents(element)调用Scope,也就是执行了参数element。
    }
}
function  SetupLeak()
{
    //  The leak happens all at once
    AttachEvents(document.getElementById("LeakedDiv"));
}
/script
/head
body onload = "SetupLeak()"  onunload = "BreakLeak()"
div id = "LeakedDiv"/div
/body
/html

来源:https://www.tulaoshi.com/n/20160220/1632458.html

延伸阅读
标签: Web开发
1.当前系统区域设置格式(toLocaleDateString和toLocaleTimeString) 例子:(new Date()).toLocaleDateString() + " " + (new Date()).toLocaleTimeString() 结果: 2008年1月29日 16:13:11 2.普通字符串(toDateString和toTimeString) 例子: (new Date()).toDateString() + " " + (new Date()).toTimeString() 结果:T...
标签: Web开发
Javascript的getYear()函数本意是提取获得当前年份,比如 script type="text/javascript"var nowd = new Date();var yf = nowd.getYear();alert(yf);/script [Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行] 在IE浏览器下解释执行为正确的2008,而是FF等浏览器下则解释为108 原因则是 在 FF等浏览器内 getYear 返...
C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:“最大的长处也可能成为最大的弱点”,那么 C/C++ 应用程序正好印证了这句话。在 C/C++ 应用程序开发过程中,动态分配的内存处理不当是最常见的问题。其中,最难捉摸也最难检测的错误之一就是内存泄漏,即未能正确释放以前分配的内存的错误。偶尔发生的少量内...
标签: Web开发
scriptvar str="abcdefghijklmnopqrstuvwxyz";document.write("字符串"+str+"中从前到后pq出现的位置是:"+str.indexOf('pq',6)+'br');document.write("字符串"+str+"中从后到前pq出现的位置是:"+str.lastIndexOf('pq',1)+'br');/script 上段代码不...
本文将介绍内存泄漏的检测方法以及现在可以使用的工具。针对内存泄漏的问题,本文提供足够的信息,使我们能够在不同的工具中做出选择。 内存泄漏 在此,谈论的是程序设计中内存泄漏和错误的问题,不过,并不是所有的程序都有这一问题。首先,泄漏等一些内存方面的问题在有的程序语言中是不容易发生的。这些程序语言一般都认为...

经验教程

335

收藏

88
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部