2014-12-20 52 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

相關問題