`

EXT的destroy方法是不是存在漏洞?

阅读更多
EXT的destroy方法是不是存在漏洞?销毁的不彻底?

利用
http://fins.iteye.com/blog/172891
提到的工具,在IE下对EXT进行测试

只是一个简单的页面,页面内只是简单的定义一个简单的window ,如下
	var win=new Ext.Window({title:"my window",
			width:400,
			draggable : false,
			shadow : false,
			resizable : false,
			shim :false,
			autoDestroy : true,
			height:300});

关闭这个window时 产生很多ie无法自动回收的孤立结点
每次创建 关闭 创建 关闭  ....
孤立结点都会越来越多

也许这是IE的错 但是EXT不应该忽视IE的 毕竟IE的占有率在那里放着呢

还请大家帮忙分析分析

我看了一下 window/panel的destroy方法似乎确实存在着一些缺陷啊

我重写了 window的destroy方法,效果提升一些,一些顽固结点可以删除了
但是还剩下一下更加顽固的结点无法删除
Ext.Window.prototype.beforeDestroy = function(){

       Ext.Window.superclass.beforeDestroy.call(this);

        Ext.destroy(

			this.header,
            this.tbar,
            this.bbar,
            this.footer,
            this.body,
			this.bwrap,
			this.focusEl,
			this.toolTarget,

			this.resizer,
            this.dd,
            this.proxy,
            this.mask
        );

			this.header=null;
            this.tbar=null;
            this.bbar=null;
            this.footer=null;
            this.body=null;
			this.bwrap=null;
			this.focusEl=null;
			this.toolTarget=null;

			this.resizer=null;
            this.dd=null;
            this.proxy=null;
            this.mask=null;


    }


这个问题如果不弄明白, 在一个复杂的ext页面内,随着操作的增加 内存消耗也将越来越大.
deskto那个例子里的 窗口 大家打开关闭打开关闭 几个来回之后内存占用就会达到6 7十M了.


我怀疑 ext的各个组件的destroy方法内部的实现考虑的不够全面, 销毁内容 和销毁顺序 不当造成部分元素无法销毁.
希望大家能够一起讨论分析一下ext的问题到底处在哪里


分享到:
评论
16 楼 gdipkf1986 2008-03-19  
呵呵,等着楼主的解决方法.自己目前还没有这个能力去做这个事情.
15 楼 fins 2008-03-19  
找到解决办法了 一会发新帖

=======================

收回上面的话 虽然可以解决 但是会打乱ext的依赖 再想想先
14 楼 znjq 2008-03-19  
我的意思是为了证明问题原因注释掉测试一下。
还是等ext自己去解决,或者自己小心使用了。呵呵
13 楼 nihongye 2008-03-18  
引用
觉的还是这2行的问题
Java代码 复制代码

   1. fn._handlers = fn._handlers || []; 
   2. fn._handlers.push([Ext.id(el), ename, h]); 

        fn._handlers = fn._handlers || [];
        fn._handlers.push([Ext.id(el), ename, h]);


这里的_handlers只在Eventmanager里面stopListening的时候做判断才用到,别的地方没看到过。感觉这里设计的有点多余,别的地方removeListener的时候又没有处理这块. 可能eventmanager和ext-base是不同人写的,呵呵。
你把这2行注释掉,就不会出现上面的内存问题了

注释掉恐怕不行,因为实际有些地方使用了el.un(...,fn)的方式停止监听,在ext的论坛上搜索_handlers destory,可以找到一篇11份的帖子提到这个问题,ext的开发人员在一些相关的回答中隐约说了要解决这个问题。假如ext本身保证了以非global function作为监听器,或者我们小心点去避免这个问题,呵呵。
12 楼 znjq 2008-03-18  
觉的还是这2行的问题
        fn._handlers = fn._handlers || [];
        fn._handlers.push([Ext.id(el), ename, h]);

这里的_handlers只在Eventmanager里面stopListening的时候做判断才用到,别的地方没看到过。感觉这里设计的有点多余,别的地方removeListener的时候又没有处理这块. 可能eventmanager和ext-base是不同人写的,呵呵。
你把这2行注释掉,就不会出现上面的内存问题了
11 楼 fins 2008-03-18  
我刚才看了一下  purgeElement 方法到最后还是调用了 stopLisener吧
=====================
(又仔细看了一下 没掉 呵呵  un方法调用了 但是destroy里的那个 removeAllLisener没有调 呵呵 我看错了 )

我觉得问题的关键是 ext的一个地方设计的有问题

他应该先 wrap 后备份

也就是说  ext-base.js 第240行的
var wrappedFn = function(e) {
                    return typeof Ext != 'undefined' ? fn(Ext.lib.Event.getEvent(e)) : false;
                };


这个操作应该早做 不应该在这一部里做
应该在 eventmanage.js 里的 addListener(205行)里做
先wrap 之后完全操作的是这个wrap之后的function

10 楼 fins 2008-03-18  
谢谢2位 你们提供的线索很重要啊 呵呵
我打算想办法改写一下ext的这个问题

到时候有不明白的还要请教2位 谢谢了先

另外最近我的一个工作就是优化ext (减少EXT对内存和cpu资源的占用)
由于之前并不是很了解ext的架构 所以想听听大家的建议

希望有同好者可以和我一起研究 谢谢了
9 楼 znjq 2008-03-18  
nihongye 的分析是正确的。
on的加入是通过EventManager的addListener方法来做的,这里在每个fn上绑定了_handlers,purgeElement的时候通过Ext.lib.Event的removeListener方法,
见300行
                delete listeners[index][this.WFN];
                delete listeners[index][this.FN];

但是这里是只是删除了fn,没有清楚掉里面的handlers,而handlers有el的引用,因为没法清楚对象.而这个时候fn也就是alertMsg是在window下的,我测了一下,单纯删除他是没用的,必须wrap一下,所以出现了你说的必须用function(){
   alertMsg()
}
才正确的情况
8 楼 nihongye 2008-03-18  
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <link rel="stylesheet" type="text/css" href="/script/yuiExt/resources/css/ext-all.css" />
  <script type="text/javascript" src="/script/yuiExt/adapter/ext/ext-base.js"></script>
  <script type="text/javascript" src="/script/yuiExt/ext-all.js"></script>
  <script type="text/javascript">


  function alertMsg(){
          alert('click div c');
  }

  function addEventDiv(){
      if (!Ext.get("div1") ){
          return;
      }
      // 使用下面这种方式注册事件 , 那么ext无法正确的移除
      Ext.get("div1").on("click",alertMsg);


  }


  Ext.onReady(function(){

      Ext.get("btn1").on("click",addEventDiv);
      Ext.get("btn2").on("click",function(){
		  Ext.destroy(Ext.get("div1"));
		  alert(alertMsg._handlers.length);
		  alert(alertMsg._handlers[0][0]);
		  alert(alertMsg._handlers[0][1]);
		  alert(alertMsg._handlers[0][2]);
	  });



  });



  </script>
  </head>
  <body >
  <input id="btn1" type="button"  value=" 为 div1 添加事件 " />
  <input id="btn2" type="button"  value=" 移除 div1 " />

  <div id="div1">I'm div 1</div>
  </body>
 </html>  


发现问题在于ext的 wrap function,就是listener是global的话就会有问题。
见 EventManager.js的140行:
        fn._handlers = fn._handlers || [];

        fn._handlers.push([Ext.id(el), ename, h]);

这里给传入的listener加了_handlers属性,stopLisener负责清除,那么就能正确的处理。
但是destroy直接调用了E.purgeElement...,这个方法好像没办法看到原来的listen,所以,没办法正确的清除_handlers,而_handlers引用了element
7 楼 nihongye 2008-03-18  

但其实ext已经用传入的function包装了一个新的function,然后才绑定到节点去。
6 楼 fins 2008-03-18  
en  代码上确实没找到什么问题
但是实际情况就是无法移除
而如果用下面的方法给上面代码中的 div注册事件 那么就可以移除:

Ext.get("div1").on("click",function(){ alertMsg() }); 
5 楼 nihongye 2008-03-18  
前几天也研究过这里的代码,看不出漏洞在那,lisenter的移除,节点的移除都是正确的。。。
4 楼 fins 2008-03-18  
下面这段代码也有问题
看来 ext的 Ext.destroy 果然不够强大
问题还是出在事件管理方面
疑惑中


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" />
<script type="text/javascript" src="../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-all.js"></script>
<script type="text/javascript">


function alertMsg(){
		alert('click div c');
}

function addEventDiv(){
	if (!Ext.get("div1") ){
		return;
	}
	// 使用下面这种方式注册事件 , 那么ext无法正确的移除  
	Ext.get("div1").on("click",alertMsg);


}


Ext.onReady(function(){

	Ext.get("btn1").on("click",addEventDiv);
	Ext.get("btn2").on("click",function(){ Ext.destroy(Ext.get("div1")); });

	
});



</script>
</head>
<body >
<input id="btn1" type="button"  value=" 为 div1 添加事件 " />
<input id="btn2" type="button"  value=" 移除 div1 " />

<div id="div1">I'm div 1</div>
</body>
</html>
3 楼 fins 2008-03-18  
问题的根本原因找到了

一会儿单独发帖讨论
2 楼 nihongye 2008-03-18  
ext1.1 里启用垃圾回收后,等30秒才从Element的cache里清除。
刷新页面后内存还占用?
1 楼 fins 2008-03-18  
jack要让我疯狂了!!!!
为了找出问题所在 我一行行的分析 2.02版本代码的 太辛苦了
看到一个地方彻底崩溃了
Template.js   204行
return returnEl ? Ext.get(newNode, true) : newNode;
注意  Ext.get(newNode, true)


再来看 Ext.get 方法的代码

Element.js 2880行

El.get = function(el){
    var ex, elm, id;
    if(!el){ return null; }
    if(typeof el == "string"){ // element id
        if(!(elm = document.getElementById(el))){
            return null;
        }
        if(ex = El.cache[el]){
            ex.dom = elm;
        }else{
            ex = El.cache[el] = new El(elm);
        }
        return ex;
    }else if(el.tagName){ // dom element
        if(!(id = el.id)){
            id = Ext.id(el);
        }
        if(ex = El.cache[id]){
            ex.dom = el;
        }else{
            ex = El.cache[id] = new El(el);
        }
        return ex;
    }else if(el instanceof El){
        if(el != docEl){
            el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
                                                          // catch case where it hasn't been appended
            El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
        }
        return el;
    }else if(el.isComposite){
        return el;
    }else if(Ext.isArray(el)){
        return El.select(el);
    }else if(el == document){
        // create a bogus element object representing the document object
        if(!docEl){
            var f = function(){};
            f.prototype = El.prototype;
            docEl = new f();
            docEl.dom = document;
        }
        return docEl;
    }
    return null;
};

// 省去一些.....

Ext.get = El.get;


我是绞尽脑汁也没弄明白那个true是做什么的

我怀疑这个地方jack弄错了
他本意可能是要给 get弄一个是否从cache里取对象的参数吧
但是没有写.



相关推荐

    如何检测Unity3D中的Gameobject的destroy事件来触发其他操作?2

    在上述的魔法特效脚本中,`Start()`方法里就使用了`Destroy(gameObject, destroyTime)`来设置对象在一定时间后自动销毁。 3. **碰撞检测与刚体(Rigidbody)**: 如果你需要在游戏对象被销毁前检测碰撞,你需要为...

    JAVA项目实践,URL存在跨站漏洞,注入漏洞解决方案.docx

    ### JAVA项目实践:URL存在的跨站漏洞与注入漏洞解决方案 #### 一、跨网站脚本(XSS)概述 跨网站脚本(Cross-site scripting,通常简称为XSS或跨站脚本攻击)是一种常见的安全漏洞攻击方式,尤其针对网站应用程序。...

    destroy

    标题“destroy”所指的可能是一款名为“桌面破坏”(Desktop Destroy)的软件,它作为一个发泄工具,让用户可以通过虚拟的方式“砸桌面”,从而在电脑上体验一种减压的乐趣。这款软件的设计理念是为了提供一种轻松的...

    EXT核心API详解

    EXT核心API详解 1、Ext类 ………………………………… 2 2、Array类 …………………………… 4 3、Number类 …………………………… 4 4、String类 …………………………… 4 5、Date类 ……………………………… 5 ...

    Ext window的使用

    - **配置项**:包括`modal`(是否为模态窗口)、`draggable`(是否可拖动)、`resizable`(是否可调整大小)、`closeAction`(关闭窗口时的行为,如`destroy`或`hide`)等。 - **方法**:`show`用于显示窗口,`...

    EXT核心API详解.doc

    5. `destroy`: 这是一个通用销毁方法,可以尝试移除传入的DOM元素、事件监听器,并调用它们的`destroy`方法(如果存在)。它有助于清理资源,防止内存泄漏。 6. `each`: 用于遍历数组或NodeList,并对每个元素执行...

    EXT中文api

    它包含了许多配置项,如id、xtype、style等,以及方法如show、hide、destroy等,用于控制组件的显示、隐藏和销毁。 在EXT中文API中,开发者可以找到关于EXT Grid、EXT Form、EXT Window、EXT Chart等关键组件的详细...

    ext内存泄露的两个补兵

    - 组件销毁:确保正确调用`destroy`方法来销毁EXT组件。这将清理组件及其关联的DOM元素和资源。 - DOM元素处理:在组件销毁时,除了调用`destroy`,还需要检查并手动清理可能存在的DOM元素引用。 2. 使用内存...

    Ext.js核心函数详解.docx

    items)`: 这个方法用于销毁一个或多个`Ext.Element`或`Ext.Component`,清理它们的事件监听器,删除DOM节点,并调用对象的`destroy`方法(如果存在)。 这些是Ext.js中的一些核心函数,它们在开发复杂的交互式Web...

    android 加载fragment防止destroy

    之前写了一个activity加载fragment的比较low,那个是放在xml布局里面动态控制show和hide实现的,这个代码也是通过show和hide实现显示和隐藏防止destroy,但是可以动态加载fragment实例,不用再把fragment放在xml布局...

    Ext中的tabpanel关闭后再打开不显示的问题

    这里通过`Ext.getCmp('activeTest')`找到指定ID的面板,并通过`.show()`方法使其可见,再使用`unhideTabStripItem`方法恢复标签栏中的显示。 #### 总结 通过以上两种方法——调整`autoDestroy`和`closeAction`属性...

    Ext js2.1 最新资料汇总

    此方法尝试销毁传入的每个对象,包括移除 DOM 节点、事件监听器,并调用它们的 `destroy` 方法(如果存在)。 **示例代码:** ```javascript var element = document.getElementById('some-element'); destroy...

    java web 期末复习题库(便于打印)

    当访问一个 Servlet 时,...C 判断指定名字的 HTTP 文件头是否存在 D 向客户端发送错误信息 pageContext 对象的 findAttribute() 方法的作用是 A.用来设置默认页面的范围或指定范围之中的已命名对象 B.用来删除默

Global site tag (gtag.js) - Google Analytics