声明:由于本人水平有限,请各位见谅,如果有任何疑问请参阅原文,hrft:http://javascript.crockford.com/memory/leak.html
author:Douglas Crockford
当一个系统不能正确的管理它的内存分配,就称之为内存泄露,这是一种BUG,其症状包括执行效率的降低和程序运行失败。
IE包含大量的泄露,最坏的一种发生在与JSCRIPT的交互过程中。当一个DOM对象包含了一个指向JS对象的引用(例如一个事件处理函数),而该JS对象也同时包含该DOM对象的引用时,一个循环结构形成了,在JS里这并不是一个问题,在这种情况下如果没有其他的引用指向这个DOM对象和事件处理句柄,垃圾回收器(一种自动管理内存的装置)将回收他们。而不幸的是,当一个死循环发生时,内存回收就不会发生了,因此发生内存泄露,随着时间的推移,内存被耗尽,内存空间充满正在使用的CELL时,浏览器就就挂起了。
我们可以举个例子,在一个程序(queuetest1)中,我们不停的创建10000个DOM元素,与此同时,删除掉除了最近创建的10个元素外的所有元素,当你打开任务管理器查看时,你将会看到PF(page file,即页面文件)的使用率任然保持在一个几乎恒定的水平上。PF使用率的改变可以作为内存分配无效的标志(原文:Changes on PF Usage can be an indicator of memory allocation inefficiency.)。
随后,我们运行第二个程序,queuetest2,它和第一个程序做的事情几乎相同,但不同的是他为每个元素增加了一个单击事件的处理器(click handler),在Mozilla和Opera中,PF使用率几乎保持不变,而在IE中,我们可以看到因为内存的泄露而引起的PF使用率以MB/S的速度稳步增长,通常情况下这种内存泄露经常被忽视。但是随着AJAX技术变得越来越流行,造成一张页面在浏览器中停留的时间也就越长,这种情况下对同一张页面操作的增加,就更有可能造成失败。
因为IE在回收循环上的失败,这幅担子不可避免的落到了我们头上,如果我们显式的破坏循环,IE就可以成功的回收内存了。但是根据Microsoft官方的观点,闭包(closure)是引起内存泄露(memory leaks)的元凶,这当然是极端错误的观点。由此看来,在有关如何处理微软BUG方面,微软提供了非常坏的建议。事实证明了我们可以很容易的在DOM这一边上破坏循环,从而解决问题,而不大可能在JSCRIPT的那一端把死循环破坏掉。
因此,可以这样来解决上述问题:
我们在完成一个元素的操作后,必须将元素的事件处理器置空以便退出可能存在的死循环,我们可以将元素的事件处理器属性赋值为NULL来解决这个问题。这可以作为一个规范来完成,或者我们写一个通用的purge函数来完成这一任务。
purge函数可以接受一个DOM元素作为它的参数。它对元素的各个属性进行循环比较,将任何值为函数的属性置为null,这样就退出了可能存在的死循环,允许占用的资源被回收。purge函数也将检查元素的后代元素,并同样破坏它们所有可能的死循环。当然,专门为IE浏览器处理内存回收BUG而定制的purge函数运行在Mozilla和Opera上是无害的。要注意的是,应当在移除元素、移除子元素,和设定该元素的innerHTML之前调用purge函数。
下面给出purge函数的代码:
function purge(d) {
var a = d.attributes, i, l, n;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
n = a[i].name;
if (typeof d[n] === 'function') {
d[n] = null;
}
}
}
a = d.childNodes;
if (a) {
l = a.length;
for (i = 0; i < l; i += 1) {
purge(d.childNodes[i]);
}
}
}
我们在IE上运行第三个程序queuetest3,在queuetest3中,移除DOM元素之前purge函数将会被调用。
----------------------------------------------------------------------------------------------------
update:微软宣称已经修复了这个代号为929874的问题,如果你确信你所有的用户都对微软的这个BUG修复感到满意,那么你可以不在你的程序中调用purge函数。而不幸的是,至今我们还不能作出定论,所以建议在IE6上的程序中仍然使用purge函数。
这就是web的特点,修补一个bug并不一定代表bug就再也不会存在。
分享到:
- 2008-07-04 08:44
- 浏览 909
- 评论(3)
- 论坛回复 / 浏览 (3 / 2407)
- 查看更多
相关推荐
JavaScript内存泄露问题的解析 JavaScript内存泄露问题是一种常见的bug,它会导致系统崩溃和性能下降。内存泄露是指系统不能正确地管理内存分配的情况,这可能会导致程序调用失败、执行减慢等问题。 在JavaScript...
由于IE浏览器的JavaScript引擎(JScript)与其他现代浏览器(如Chrome的V8引擎)存在差异,它可能存在一些特有的内存泄漏问题。该工具可以帮助开发者识别和定位IE浏览器中的内存泄漏问题,提升网页在IE下的性能。 4...
AQTime是一款强大的代码分析工具,尤其擅长于内存泄漏和资源泄漏的监控,广泛应用于.NET和JAVA应用程序。它由AutomatedQA公司开发,可与Visual Studio或Embarcadero RAD Studio集成,提供全面的性能和资源调试功能。...
2. **内存泄漏类型**:常见的JavaScript内存泄露包括全局变量、闭包引用、DOM元素引用、事件监听器等。了解这些类型有助于识别潜在问题。 3. **工具使用**:利用如IE Developer Tools(F12工具)、Chrome DevTools...
了解JScript性能优化技巧,如减少全局变量的使用、避免内存泄漏、合理使用缓存等,有助于提高代码运行效率。 9. **JScript与JavaScript的区别** 虽然名字相似,但JScript和JavaScript并非完全相同。了解两者在...
4. **事件处理器泄漏**:未正确解除的事件监听器也可能导致内存泄露,因为它们仍然保有对元素的引用。 5. **定时器和回调函数**:长时间运行的定时器或者未取消的回调函数可能导致内存被长期占用。 6. **诊断和...
7. 性能优化:学习如何编写高效的JavaScript代码,避免内存泄漏,提升网页性能。 8. 测试与调试:了解如何使用开发者工具进行代码调试,进行单元测试和集成测试。 五、实战经验 通过参与实际项目或构建个人项目,...
页面之间的关系保持简单,并且在同一站点的不同地址之间进行导航可以快速地清理任何内存泄漏问题。如果存在泄漏,也小到足以忽略。新的Web应用需要实践更高的标准。一个页面可能运行数小时,而不会被导航或者通过Web...
JScript的发展中存在一些缺陷和问题,特别是在内存管理和Bug方面。接下来,我们将详细探讨JScript的Bug和内存管理知识点,以帮助开发者更好地理解和规避这些问题。 首先,JScript中关于命名函数表达式存在一些问题...
JavaScript在IE9之前的版本中,内存管理机制与现代浏览器有所不同,导致了一些特有的内存泄露问题。在IE9之前,JavaScript引擎JScript使用了两种不同的垃圾回收策略:对于JScript对象使用了"标记-清除"算法,而对于...
本文将对其中的关键概念进行总结,包括运算符、字符串处理、图片显示、变量声明、常量定义、for循环、闭包以及闭包引发的内存泄漏问题。 1. **运算符与表达式**: - 运算符是执行特定操作的符号,如加法`+`、减法`...
尽量减少全局变量的使用,以防止命名冲突和内存泄漏。 ### 其他编码规则 1. **空格和括号**:使用空格来提高可读性,例如在操作符前后、括号内等。遵循一致的括号配对规则,如函数调用和对象字面量。 2. **命名...
这部分内容通过代码片段和内存转储(dump)分析,展示了攻击者如何在JScript9环境下构造攻击载荷。 总结来说,文章探讨了当前网络攻击场景下,攻击者如何通过各种技术手段,包括对旧版本的JavaScript引擎利用、对新...
在JScript中引入的CollectGarbage()过程,尽管它被称为GC(垃圾回收)过程,但它实际上并不保证立即回收内存。在某些情况下,开发者可以尝试调用CollectGarbage()来尝试清除“失效的对象实例”,即调用对象的析构...
- **优化事件处理**:合理注册和注销事件监听器,避免内存泄漏。 **4.2 JScript语言本身的优化** **4.3 DOM相关** DOM操作通常是影响网页性能的关键因素之一。合理地组织DOM结构和减少DOM访问次数可以显著提高...
在编程实践中,使用ADODB.Stream进行文件操作要谨慎,因为COM对象的创建和销毁在JavaScript中可能引起内存泄漏,而且在非IE浏览器中无法直接使用ActiveXObject。此外,脚本权限的安全设置也可能限制对文件系统的访问...
除了基本的断点设置、单步执行外,Windbg还具有内存查看、调用堆栈分析、模块与线程管理、内存泄漏检测等功能。 **2. 安装与启动Windbg** 首先,你需要下载并安装Windbg。安装完成后,可以通过桌面快捷方式或开始...