Discuz教程网

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

[复制链接]
authicon Qin328 发表于 2012-3-22 04:27:39 | 显示全部楼层 |阅读模式
可能有人不知道上面Bug截图的图片是啥,那是Firebug的DOM截图
  aimgcount是浏览帖子中未缩放的图片的信息集合, 2544217是pid值,其下的1283199是图片的aid。   
  那么图中箭头所指多个undefined是啥? 不急,我们先做个试验:逐步修改这帖的pid以及关联图片的pid(后一个操作是让该图片依旧属于其帖子)。然后在chrome中观察内存占用

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        
删除图片,内存消耗恢复正常

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        
那如果改成 412345678结果如何呢?

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        
内存消耗对比:
  

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
        
为什么随着帖子pid的增加内存耗用会大幅度增长呢?
  答案就是这么一段代码(来自dz7.2):
它来自于 viewthread.htm。在这儿定义了一个 aimgcount的数组变量,然后在 viewthread_node.htm 中进行赋值:


    上面这段代码把帖子中未缩放图片的aid写入到aimgcount 数组变量中
      
      问题根源在于javascript的数组是稀疏数组(本质上是个对象),而不是PHP那种链表型数组,开发人员拿数组来保存hash类型结构结果就导致 aimgcount 数组产生空洞——pid值越大,空洞越大
      
      当pid为25442177时,我在本地测试消耗内存72M左右,帖子测试是30M左右。内存消耗后者增长不明显,原因不明。内存消耗是一方面,另外一个重要影响是js数组检索性能下降,比如 attachimgshow(pid) 函数在渲染图片时就需要检索 aimgcount这个变量。
    而让开发人员头大的是这会导致调试困难——你打开上面这个dz帖子链接,然后再激活firebug窗口(包括DOM面板)。看看结果是不是这样:

    钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

    钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
            
      
    结论是用js数组变量保存pid及对应aid的做法存在巨大(客户端)性能隐患——随着论坛营运,pid越来越大,数组会越来越稀疏。占用浏览器内存越来越多,浏览器速度越来越慢。
      
      此bug从Discuz7.2到X3.0都存在
      
      解决办法简单得让你无法相信——用js对象替代即可,修改 viewthread.htm为:
    viewthread_node.htm的赋值语句并不需要修改,这是因为js对于对象灵活的访问机制:可以使用. (句点)和 [] (方括号)来访问并设置js对象。
      
      另外一处需要修改的是 trade_info.htm,找到如下的:

    依法修改即可
      是否还有其他文件需要修改,暂无发现。
      
      
      ps:最后再来看看第一张截图
            

    钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!

    钻石恒久远一坑永流传 Javascript超级无敌通古斯天坑 Discuz所有版本通杀!
            
      
          
      下方那个 aimgs是啥呢?
      它来自于 viewthread.js


    1. function attachimgshow(pid) {

    2.     aimgs = aimgcount[pid];

    3.     aimgcomplete = 0;

    4.     loadingcount = 0;

    5.     for(i = 0;i < aimgs.length;i++) {

    6.         obj = $('aimg_' + aimgs);

    7. .....
    复制代码

    attachimgshow()函数中 aimgs本来是个局部变量,但因为未加上 var 定义就变成了全局变量,虽然未造成啥问题,但这是不严谨的代码。同样的问题在上方代码中也有,见for循环中 obj 这个变量以及aimgcomplete,loadingcount 也都定义成了全局变量,至于控制for循环次数的 i 变量就不奢望了。就这么短短一段代码就多处漏洞,唉……
      
      严谨的写法应该如此:







    1. function attachimgshow(pid) {

    2.     var aimgs = (window.aimgcount)[pid],

    3.           aimgcomplete = 0,

    4.           lloadingcount = 0,

    5.           obj;

    6.     if (!aimgs) { return false; }

    7.     for(var i = 0; i < aimgs.length; i++) {

    8.         obj = $('aimg_' + aimgs);

    9. .....
    复制代码
    aimgs.length因为不会太大,所以对于for循环不做缓存不会有啥性能损失。另外一个要注意的是window.aimgcount这样的写法,加不加window这对运行没任何影响,但显式声明会让维护人员少花些精力去猜测和调试
    钻石恒久远,一坑永流传
    没想到此等远古坑居然被我发掘到。哈哈
    填完收工 :)
    ADD: 有人没看明白此bug,简要总结下。
    dz程序js代码对变量类型使用失误,结果是当论坛发帖量足够**id足够大时,如果此帖内有未经dz后台缩放过的图片,那么在浏览的时候会造成浏览器页面消耗的内存增加,速度减慢甚至崩溃,尤其是是firebug调试时更明显。pid越大,症状越明显。
    此bug在dz7.2出现,X3.0上面依然存在。
    解释下这个js稀疏数组:js的数组对象与php的数组不同,php你可以使用



      1. $arr[3] = 123;
      复制代码
      来赋值,这个数组只有一个元素,数组长度是1. 而js中




        1. var arr = new Array();
        2. arr[3] = 123;
        复制代码
        复制代码
        赋值的结果是 arr[undefined, undefined, undefined, 123] , arr[3] === 123 . 只有一个元素但是长度为4. 如果下标非常大,比如






    1. arr[12345678] = 123;
    复制代码

    那么此数组会变成超级稀疏,会让遍历性能下降许多。尤其是是在debug调试时。



上一篇:这个难道是论坛漏洞??
下一篇:国际时间误差问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1314学习网 ( 浙ICP备10214163号 )

GMT+8, 2025-5-1 23:43

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表