2014-12-20 50 views
-1

情景发现是什么原因造成这个Windows小工具

我使用的是Windows小工具平台,这个小工具的内存泄漏:

http://win7gadgets.com/pc-system/sushis_driveinfo.html

问题

该小工具有内存泄漏,如果我k eep运行这个小工具+ 24小时。它可以增加RAM消耗高达1 GB,而其他类似的小工具不会产生这种情况,所以我放弃了这是一个sidebar.exe内存管理,而不是,是一个脚本错误。

如果有更多时间运行小工具,则更多无响应成为小工具(点击时)。

我对JavaScript的认识是空的,但无论如何我能理解语法并试图理解开发人员在这段代码中做了什么,我认为问题在于管理图像对象,但在我看来,在每次手术后似乎都要妥善处理这些物品。

QUESTION

这是小工具来源。

有人可以帮助我发现并修复导致此小工具中内存泄漏的原因?

sushi_driveinfo.html(主窗口):

<html> 
    <head> 
    <title>Drive Info</title> 
    <style> 
     body { margin: 0; padding: 0; width: 156px; height: 200px; background-image: url(images\canvas.png); color: #ffffff; font-family: 'Segoe UI'; } 
     #targets { position: absolute; top: 0; left: 0; } 
     .target { position: absolute; width: 156px; height: 48; left: 0; cursor: hand; } 
    </style> 
    <script type="text/javascript"> 
     var lst = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
     var timeout = null; 
     var drives = new Array(26); 
     var drvchk = new Array(26); 
     var drvspc = new Array(26); 
     var vizchg = false; 
     var current_y = 0; 
     var background,theme,remove,local,network,media,show_pc,show_net; 
     var item_height=48; 
     var icon_offset=20; 
     var text_offset=72; 
     var meter_offset=24; 

     function convertBytes(b) 
     { 
     var i = 0, u = Array(' MB', ' GB', ' TB'); 
     while (b >= 1024 && (b /= 1024) >= 1) i++; 
     return (Math.round(b * 100)/100) + u[i]; 
     } 

     function openDrive() 
     {   
     var d = window.event.srcElement.getAttribute('drive');  
     System.Shell.execute(d + ':\\'); 
     return; 
     } 

     function openNetwork() 
     {   
     System.Shell.execute("Explorer", "/N,::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}"); 
     return; 
     } 

     function openComputer() 
     {   
     System.Shell.execute("Explorer", "/N,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"); 
     return; 
     } 

     function recheckDrives() { 
     for(var i = 0; i < 26; i++) 
     { 
      if (!drives[i]) { 
      drives[i] = System.Shell.drive(lst.charAt(i)); 
      if (drives[i]) { vizchg = true; drvchk[i] = true; } 
      } else { 
      if (drives[i].isReady != drvchk[i]) { drvchk[i] = !drvchk[i]; vizchg = true; } 
      if (drives[i].isReady && drives[i].freeSpace != drvspc[i]) { drvspc[i] = drives[i].freeSpace; vizchg = true; } 
      } 
     } 
     } 

     function calcHeight(h) { 
     var y=0; 
     if(show_pc==2) y+=h; 
     if(show_net==2) y+=h; 
     for(var i=0;i<26;i++) 
      if(isDriveVisible(i)) y+=h; 
     return y; 
     } 

     function isDriveVisible(i) { 
     if(drvchk[i]) { 
      if  (drives[i].driveType == 2 && remove == 1) ; 
      else if (drives[i].driveType == 3 && local == 1) ; 
      else if (drives[i].driveType == 4 && network == 1) ; 
      else if (drives[i].driveType == 5 && media == 1) ; 
      else if (drives[i].driveType == 1 || drives[i].driveType == 6) ; 
      else 
      return true; 
     } 
     return false; 
     } 

     function paintPC() { 
     if (show_pc == 2) { 
      canvas.addImageObject('images/backgrounds/background' + background + 's.png', 0, current_y); 
      var di=canvas.addImageObject('images/drives/pc'+ theme +'.png', icon_offset, current_y); 
      di.width*=0.8; 
      di.height*=0.8; 
      canvas.addTextObject('Computer', 'Segoe UI', 11, 'white', text_offset, current_y + 5); 
      var b = document.createElement('DIV'); 
      b.className = 'target'; 
      b.style.posTop = current_y; 
      b.onclick = openComputer; 
      targets.appendChild(b); 
      current_y+=item_height; 
     } 
     return; 
     } 

     function paintNET() { 
     if (show_net == 2) { 
      canvas.addImageObject('images/backgrounds/background' + background + 's.png', 0, current_y); 
      var di=canvas.addImageObject('images/drives/net'+ theme +'.png', icon_offset, current_y); 
      di.width*=0.8; 
      di.height*=0.8; 
      canvas.addTextObject('Network', 'Segoe UI', 11, 'white', text_offset, current_y + 5); 
      var b = document.createElement('DIV'); 
      b.className = 'target'; 
      b.style.posTop = current_y; 
      b.onclick = openNetwork; 
      targets.appendChild(b); 
      current_y+=item_height; 
     } 
     return; 
     } 

     function paintGadget() 
     {  
     try { 
     recheckDrives(); 
     if (!vizchg) return; 

     var total_height=calcHeight(item_height); 
     System.Gadget.beginTransition(); 

     document.body.style.height=total_height; 
     canvas.style.height=total_height; 
     canvas.removeObjects(); 
     targets.innerHtml = ''; 

     current_y = 0; 
     paintPC(); 
     paintNET(); 
     for(i = 0; i < 26; i++) 
     { 
      if(isDriveVisible(i)) { 
       if (drives[i].freeSpace != 0) { 
       canvas.addImageObject('images/backgrounds/background' + background + '.png', 0, current_y); 
       var f = Math.round(drives[i].freeSpace/drives[i].totalSize * 100); 
       var u = (100 - f); 
       canvas.addTextObject(convertBytes(drives[i].freeSpace) + '/' + f + '%', 'Segoe UI', 10, 'white', text_offset, current_y + 17); 
       var m = canvas.addImageObject('images/meter' + (u < 90 ? 'blue': (u < 98 ? 'orange': 'red')) + '.png', meter_offset, current_y + 34); 
       m.width = Math.floor((u * 128/100)); 
       m.left = 24 - Math.floor(((128 - m.width)/2)); 
       } else { 
       canvas.addImageObject('images/backgrounds/background' + background + 's.png', 0, current_y); 
       canvas.addTextObject(convertBytes(drives[i].totalSize), 'Segoe UI', 10, 'white', text_offset, current_y + 17); 
       } 

       var di=canvas.addImageObject('images/drives/drive' + drives[i].driveType + theme + '.png', icon_offset, current_y-5); 
       di.width*=0.8; 
       di.height*=0.8; 
       canvas.addTextObject(drives[i].volumeLabel + ' (' + drives[i].driveLetter + ':)', 'Segoe UI', 11, 'white', text_offset, current_y + 5); 
       var o = document.createElement('DIV'); 
       o.className = 'target'; 
       o.style.posTop = current_y; 
       o.setAttribute('drive', drives[i].driveLetter); 
       o.onclick = openDrive; 
       targets.appendChild(o); 

       current_y += item_height; 
      } 
     System.Gadget.endTransition(System.Gadget.TransitionType.morph,0.1); 
     window.setTimeout(fixCanvasBackground, 600); 
     } 
     } finally { 
     vizchg = false; 
     return; 
     } 
     } 

     function fixCanvasBackground() { 
     canvas.src = canvas.src; 
     } 

     function initDrives() 
     { 
     for(var i = 0; i < 26; i++) { 
      drives[i] = System.Shell.drive(lst.charAt(i)); 
      if (drives[i] && drives[i].isReady) 
      { drvchk[i] = true ; drvspc[i] = drives[i].freeSpace; } 
      else { drvchk[i] = false; } 
     } 
     return; 
     } 

     function onShowSettings() { 
     window.clearInterval(timeout); 
     System.Gadget.beginTransition(); 
     window.setTimeout(endTransitionFast, 400); 
     } 

     function onSettingsClosed() { 
     readSettings(); 
     timeout=window.setInterval(paintGadget, 2500); 
     vizchg=true; 
     paintGadget(); 
     } 

     function endTransitionFast() { 
     System.Gadget.endTransition(System.Gadget.TransitionType.morph, 0.1); 
     fixCanvasBackground(); 
     } 

    function readSettings() { 
     background=System.Gadget.Settings.read("background"); 
     if(background==0) { background=2; System.Gadget.Settings.write("background",2); } 
     theme=System.Gadget.Settings.read("theme"); 
     if(theme==0) { theme=1; System.Gadget.Settings.write("theme",1); } 
     show_pc=System.Gadget.Settings.read("showpc"); 
     if(show_pc==0) { show_pc=1; System.Gadget.Settings.write("showpc",1); } 
     show_net=System.Gadget.Settings.read("shownet"); 
     if(show_net==0) { show_net=1; System.Gadget.Settings.write("shownet",1); } 
     local=System.Gadget.Settings.read("local"); 
     if(local==0) { local=2; System.Gadget.Settings.write("local",2); } 
     media=System.Gadget.Settings.read("media"); 
     if(media==0) { media=2; System.Gadget.Settings.write("media",2); } 
     network=System.Gadget.Settings.read("network"); 
     if(network==0) { network=2; System.Gadget.Settings.write("network",2); } 
     remove=System.Gadget.Settings.read("remove"); 
     if(remove==0) { remove=2; System.Gadget.Settings.write("remove",2); } 
     } 

     function onLoad() 
     { 
     System.Gadget.settingsUI = "settings.html"; 
     System.Gadget.onSettingsClosed = onSettingsClosed; 
     System.Gadget.onShowSettings = onShowSettings; 

     readSettings(); 
     initDrives(); 
     timeout = window.setInterval(paintGadget, 2500); 
     vizchg = true; 
     paintGadget(); 
     return; 
     } 
    </script> 
    </head> 
    <body onload="onLoad()"> 
    <div id="targets"></div> 
    <g:background id="canvas" src="images/canvas.png" style="position: absolute; top: 0; left: 0; width: 156; height: 200; z-index: -999;" opacity="0" /> 
    </body> 
</html> 

settings.html(设置窗口):

<html> 
    <head> 
    <style> 
     body { width: 250px; height: 800px; padding: 0px; margin: 0px; font-family: Tahoma; } 
     body,p,div,span,td { font-size: 9pt; } 
     label { font-weight: bold; } 
     input,select { font: Arial; font-size: 9pt; } 
     table { width: 100%; } 
    </style> 
    <script> 
     var background, maxBackgrounds = 3, theme = 1, maxThemes = 7; 

     function updateBackground() 
     { 
     var x = 84, y = 47, m; 
     canvas.removeObjects(); 

     canvas.addImageObject('images/backgrounds/background' + background + '.png', x, y); 
     m = canvas.addImageObject('images/meterblue.png', x + 24, y + 34); 
     m.width = (0.25 * 128); 
     m.left = x + 24 - ((128 - m.width)/2); 

     canvas.addImageObject('images/drives/drive3' + theme + '.png', x, y); 
     canvas.addTextObject('Vista (C:)', 'Segoe UI', 11, 'white', x + 58, y + 5); 
     canvas.addTextObject('40GB/75%', 'Segoe UI', 10, 'white', x + 58, y + 17); 

     //y -= 20; 

     //canvas.addImageObject('images/backgrounds/background' + background + '.png', x, y); 
     //m = canvas.addImageObject('images/meterorange.png', x + 24, y + 34); 
     //m.width = (0.937 * 128); 
     //m.left = x + 24 - ((128 - m.width)/2); 

     //canvas.addImageObject('images/drives/drive3.png', x, y); 
     //canvas.addTextObject('Apps (D:)', 'Segoe UI', 11, 'white', x + 58, y + 5); 
     //canvas.addTextObject('10GB/6.3%', 'Segoe UI', 10, 'white', x + 58, y + 17); 

     canvas.addImageObject('images/drives/drive3' + theme + '.png', x-85, y+130); 
     canvas.addImageObject('images/drives/drive2' + theme + '.png', x-85, y+172); 
     canvas.addImageObject('images/drives/drive4' + theme + '.png', x-85, y+215); 
     canvas.addImageObject('images/drives/drive5' + theme + '.png', x-85, y+258); 
     } 

     function onBackground() 
     { 
     var e = window.event, o = e.srcElement, b = o.getAttribute('base'); 

     o.src = 'images/settings/' + b + (e.type == 'mouseover' || e.type == 'mouseup' ? 'hover': (e.type == 'mousedown' ? 'pressed': '')) + '.png'; 

     if (e.type == 'mouseup') 
     { 
      if (b == 'next') background++; else background--; 
      if (background < 1) background = maxBackgrounds; 
      if (background > maxBackgrounds) background = 1; 

      updateBackground();   
     } 
     } 

     function onTheme() 
     { 
     var e = window.event, o = e.srcElement, b = o.getAttribute('base'); 

     o.src = 'images/settings/' + b + (e.type == 'mouseover' || e.type == 'mouseup' ? 'hover': (e.type == 'mousedown' ? 'pressed': '')) + '.png'; 

     if (e.type == 'mouseup') 
     { 
      if (b == 'next') theme++; else theme--; 
      if (theme < 1) theme = maxThemes; 
      if (theme > maxThemes) theme = 1; 

      updateBackground();   
     } 
     } 


     function onClose(event) 
     { 
     if (event.closeAction == event.Action.commit) 
     { 
      System.Gadget.Settings.write("background", background); 
      System.Gadget.Settings.write("theme",  theme); 
      System.Gadget.Settings.write("showpc",  document.boxes.mypc.checked ? 2 : 1); 
      System.Gadget.Settings.write("shownet", document.boxes.netw.checked ? 2 : 1); 

      System.Gadget.Settings.write("remove",  document.boxes.remove.checked ? 2 : 1); 
      System.Gadget.Settings.write("local",  document.boxes.local.checked ? 2 : 1); 
      System.Gadget.Settings.write("network", document.boxes.network.checked ? 2 : 1); 
      System.Gadget.Settings.write("media",  document.boxes.media.checked ? 2 : 1); 
     } 

     event.cancel = false; 

//  System.Gadget.beginTransition(); 
//  window.setTimeout(endtransit, 400); 
     } 

/* function endtransit() { 
     System.Gadget.endTransition(System.Gadget.TransitionType.morph, 0.1); 
     }*/ 


     function onLoad() 
     { 
     var box; 
     System.Gadget.onSettingsClosing = onClose; 

     background = System.Gadget.Settings.read("background"); 
     if (background == 0) background = 2; 

     theme = System.Gadget.Settings.read("theme"); 
     if (theme == 0) theme = 1; 

     System.Gadget.Settings.read("remove") == 2 ? document.boxes.remove.checked = true : false; 
     System.Gadget.Settings.read("local") == 2 ? document.boxes.local.checked = true : false; 
     System.Gadget.Settings.read("network") == 2 ? document.boxes.network.checked = true : false; 
     System.Gadget.Settings.read("media") == 2 ? document.boxes.media.checked = true : false; 

     System.Gadget.Settings.read("showpc") == 2 ? document.boxes.mypc.checked = true : false; 
     System.Gadget.Settings.read("shownet") == 2 ? document.boxes.netw.checked = true : false; 

     updateBackground(); 
     } 
    </script> 
    </head> 
    <body onload="onLoad()"> 
    <g:background id="canvas" src="images/settings/desktop.png" style="position: absolute; left: 1; top: 1; z-index: -999;" /> 
    <div style="position: absolute; left: 0; top: 147px;"> 
     <table cellspacing="0" cellpadding="0"> 
     <tr> 
      <td style="width: 33%; padding-right: 10px;" align="right"><img src="images/settings/previous.png" base="previous" style="cursor: hand;" onmouseover="onBackground();" onmouseout="onBackground();" onmousedown="onBackground();" onmouseup="onBackground();" /></td> 
      <td style="width: 33%;" align="center"><label>Backgrounds</label></td> 
      <td style="width: 33%; padding-left: 10px;" align="left"><img src="images/settings/next.png" base="next" style="cursor: hand;" onmouseover="onBackground();" onmouseout="onBackground();" onmousedown="onBackground();" onmouseup="onBackground();" /></td> 
     </tr> 
     <tr> 
      <td style="width: 33%; padding-right: 10px;" align="right"><img src="images/settings/previous.png" base="previous" style="cursor: hand;" onmouseover="onTheme();" onmouseout="onTheme();" onmousedown="onTheme();" onmouseup="onTheme();" /></td> 
      <td style="width: 33%;" align="center"><label>Icon Theme</label></td> 
      <td style="width: 33%; padding-left: 10px;" align="left"><img src="images/settings/next.png" base="next" style="cursor: hand;" onmouseover="onTheme();" onmouseout="onTheme();" onmousedown="onTheme();" onmouseup="onTheme();" /></td> 
     </tr> 
     </table> 
     <table cellspacing="0" cellpadding="0" style="margin-top: 15px;margin-left:60px;"> 
     <tr><td> 
      <form name="boxes"> 
      <input type="checkbox" name="local"> 
       <font style="font-size: 8pt;">Local Drives</font><p> 
      <input type="checkbox" name="remove"> 
       <font style="font-size: 8pt;">Removable Drives</font><p> 
      <input type="checkbox" name="network"> 
       <font style="font-size: 8pt;">Network Drives</font><p> 
      <input type="checkbox" name="media"> 
       <font style="font-size: 8pt;">Media Drives</font><p> 
      <input type="checkbox" name="mypc"> 
       <font style="font-size: 8pt;">My Computer link</font><br> 
      <input type="checkbox" name="netw"> 
       <font style="font-size: 8pt;">Network Link</font> 
      </form> 
     </td></tr> 
     </table> 
    </div> 
    </body> 
</html> 

UPDATE:

这里是该全小工具来源,如果有帮助:

https://www.mediafire.com/?c8h1271714sp6tz

+0

尝试使用xperf/WPA来分析内存使用情况:http://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-49-WPT-Memory-Analysis-VirtualAlloc,http:// channel9。 msdn.com/Shows/Defrag-Tools/Defrag-Tools-50-WPT-Memory-Analysis-Heap – magicandre1981

+0

@ magicandre1981我已经下载并安装了WinSDK来安装xperf,但这个工具似乎是内存分析/调试专家,甚至看到你提供的例子,我不明白如何做它测试小工具的工作,谢谢反正! – ElektroStudios

回答

2

总有一个机会,他们是在系统中安装导致此上的驱动程序中的一个漏洞。但是,在查看JavaScript代码时,过去存在导致问题的模式并且现在有解决方案。

小工具的主循环是这样的:

function paintGadget() { 
    // repaint/rebuild all UI elelments 
    // remove all elements 
    targets.innerHtml = ''; 
    // buildup 
    var o = document.createElement('DIV'); 
    o.onclick = openDrive; 
    targets.appendChild(o); 
} 

function openDrive() { 
} 

window.setInterval(paintGadget, 2500); 

这基本上意味着:呼叫paintGadget每2.5秒,永远

这应该是很好,如果JavaScript引擎和它的资源当他们不在任何范围内时,垃圾被收集。而这种情况下,由于编程拙劣,事情可能会发生变化。

基于来自用户dsgthe answer我们了解到eventlisteners是垃圾回收失败的根本原因。

为了克服这个问题,我们有与删除元素它的自我,像这样前删除了每个元素的事件处理器的实现更换线targets.innerHtml = '';在功能paintGadget

while(targets.firstChild) { 
    var ch = targets.firstChild; 
    ch.onclick = null; 
    targets.removeChild(ch);    
} 

如说介绍,paintGadget特别在画布中使用类似的图案,删除所有内容并重新创建。如果在那里有泄漏,那么也需要重新实现。

+0

谢谢你的回答。 (对不起,我的英文)这个小工具总是增加了内存的消耗,直到没有任何限制,只是继续运行这个小工具,它会在确定的pc正常运行时间达到1 GB RAM。我对JS的认识是空的我只是在寻找一个解决方案来解决这个问题,但是如果我理解的很好,我只需要将paintGadget函数中的那条指令用你提供的循环代替,那么我就不需要重置innerHTML属性了吗? – ElektroStudios

+0

不幸的是,我需要花一天或更多的时间来测试我的结果,我已经实现了代码修改,并且我看到的第一个东西看起来非常好,sidebar.exe RAM通常以11 MB开头,这个小工具是将RAM增加到14 MB,然后每次减少到11 MB,这是由你的修改引起的,所以现在可能已经解决了,但是我需要花时间去发现它是否会减少内存,也许它存储垃圾,我的意思是也许现在它可以将RAM减少到11 MB,但可能在24小时内。它只能减少RAM为50 MB,这将表示一个RAM问题仍然 – ElektroStudios

+0

正如我所说的即将说它已解决或不适合我,但你认为也许代码的其他部分需要修改或您提供的修改可能够用了吗?特别感谢您对这个问题的关注。 PS:我不知道如何解决方案可能会导致一个小工具泄漏,但我敢肯定,情况并非如此,因为我与这个小工具多年来使用Win7和Win8与这个问题只有一个决定性连接/不仅在我的电脑中,它显然是一个关于内存管理的小工具问题,我想知道你的修改可以永远解决这个问题。 – ElektroStudios

相关问题