gpt4 book ai didi

javascript - 在此 Windows 小工具中查找导致内存泄漏的原因

转载 作者:行者123 更新时间:2023-11-28 19:27:26 27 4
gpt4 key购买 nike

SCENARIO

我正在将 Windows 小工具平台与此小工具结合使用:

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

PROBLEM

该小工具存在内存泄漏,如果我继续运行该小工具+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

最佳答案

总有可能是系统上安装的某个驱动程序存在泄漏,从而导致了这种情况。但是,当查看该 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);

这基本上意味着:每 2.5 秒调用一次paintGadget,永远

如果 javascript 引擎及其资源在不再处于任何范围内时被垃圾回收,那么这应该没问题。由于草率的编程,事情可能会出现问题。

基于the answer来自用户dsg我们了解到事件监听器是垃圾收集失败的根本原因。

为了解决这个问题,我们必须将函数 paintGadget 中的行 targets.innerHtml = ''; 替换为在删除之前删除每个元素上的事件处理程序的实现元素本身,如下所示:

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

正如简介中所述,paintGadget 尤其适用于 Canvas ,它遵循类似的模式,删除所有内容并重新创建。如果其中存在泄漏,也需要重新实现。

关于javascript - 在此 Windows 小工具中查找导致内存泄漏的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27578897/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com