Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/466.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何删除JavaScript画布呈现上下文的状态堆栈?_Javascript_Canvas_Memory Management_Memory Leaks_Html5 Canvas - Fatal编程技术网

如何删除JavaScript画布呈现上下文的状态堆栈?

如何删除JavaScript画布呈现上下文的状态堆栈?,javascript,canvas,memory-management,memory-leaks,html5-canvas,Javascript,Canvas,Memory Management,Memory Leaks,Html5 Canvas,我最近在用JavaScript处理,发现可能会造成非常严重的“内存泄漏”(更像是内存爆炸)。使用画布上下文时,您可以执行context.save()将图形样式添加到“状态堆栈”中,并执行context.restore()将其删除。(见附件。) 当您碰巧连续保存到状态堆栈而不还原时,就会出现问题。在Chrome v50和Firefox v45中,这似乎占用了越来越多的私有内存,最终导致浏览器选项卡崩溃。(顺便说一句,JavaScript内存在Chrome中不受影响,因此很难使用profiler/t

我最近在用JavaScript处理
,发现可能会造成非常严重的“内存泄漏”(更像是内存爆炸)。使用画布上下文时,您可以执行
context.save()
将图形样式添加到“状态堆栈”中,并执行
context.restore()
将其删除。(见附件。)

当您碰巧连续保存到状态堆栈而不还原时,就会出现问题。在Chrome v50和Firefox v45中,这似乎占用了越来越多的私有内存,最终导致浏览器选项卡崩溃。(顺便说一句,JavaScript内存在Chrome中不受影响,因此很难使用profiler/timeline工具对此进行调试。)

我的问题:如何清除或删除画布上下文的状态堆栈?使用普通数组,您可以检查
长度
,使用
拼接
对其进行修剪,或者简单地重置为空
[]
,但我还没有看到使用状态堆栈执行任何操作的方法

[一] 。。发现了造成严重“内存泄漏”的可能性

从技术上讲,这不是内存泄漏。泄漏可能是分配内存并释放指向它的指针,因此无法释放内存。在这种情况下,会跟踪指针,但不会释放内存

当您碰巧连续保存到状态堆栈而不还原时,就会出现问题

这是意料之中的。在不释放内存的情况下分配内存将累积已分配的内存块

如何清除或删除画布上下文的状态堆栈

唯一的方法是恢复所有保存的状态,或者通过为canvas元素设置一些大小(即
canvas.width=canvas.width
)来重置上下文

调用
restore()
的次数比调用
save()
的次数要多(在这种情况下,它只返回而不执行任何操作)也很安全,因此从理论上讲,您可以通过一个
n
迭代次数的循环来运行它。不过,后者更属于不良行为范畴

但话说回来:如果假设存储和恢复的数量相等,但存储和恢复的数量不匹配,则通常表示代码中的其他地方存在问题。通过重置或在post中运行多个恢复来解决问题可能只会有助于掩盖实际问题

下面是一个关于如何跟踪保存/还原调用计数的示例-

//注意:在创建画布上下文之前,需要运行此代码
CanvasRenderingContext2D.prototype.\u save=CanvasRenderingContext2D.prototype.save;
CanvasRenderingContext2D.prototype.\u restore=CanvasRenderingContext2D.prototype.restore;
//我们的补丁向量
CanvasRenderingContext2D.prototype.\uu tracker=0;
CanvasRenderingContext2D.prototype.save=函数(){
这个;
log(“Track save:,this.\u tracker”);
这个._usave()
}
CanvasRenderingContext2D.prototype.restore=函数(){
这个;
log(“跟踪还原:”,this.\u tracker);
这是.\u restore()
}
//用于转储状态的自定义方法
CanvasRenderingContext2D.prototype.trackstat=函数(){
如果(此跟踪程序)
console.warn(“跟踪状态:”,此.\u跟踪器);
其他的
日志(“跟踪状态:OK”);
}
var ctx=document.createElement(“canvas”).getContext(“2d”);
ctx.save();//执行几个save()操作
ctx.save();
ctx.restore();//单一还原()
ctx.trackstat();//应报告1的不匹配
ctx.restore();//上次还原()

ctx.trackstat();//应该报告OK
我认为您不能真正获得堆栈的“长度”。要避免这种情况,只需记住,每次不再需要保存的状态时,必须
恢复它。(还请注意,它将保存上下文的全部属性,在大多数情况下,您只需要保存一个或两个属性,我个人尽可能避免调用这个繁重的方法)。因此,您的问题的答案已经在您的问题中。我正在寻找一种解决方案,如果“简单记住”失败,它可能有助于调试。想象一下,你只是得到了一个上下文。。。你将如何清理它或者能够检测到是否存在正在进行的问题?如果有人能够解释为什么Chrome中的私有内存增加而不是JavaScript内存增加,那么你将获得额外的分数。这使得诊断非常困难。“我们需要确保我们自己跟踪推送(或保存)和POP(恢复)的数量”@Luke访问权限确实有限。您可以“修补”这些调用以保持临时跟踪,以便进行调试。我会再举一个例子来说明如何做到这一点,但这当然就像是因为脚趾疼痛而注射流感疫苗。问题表明存在设计问题。不,这确实是内存泄漏。甚至在技术上@Ryan不,泄漏是“丢失”内存。保留可以随时释放的内存只是一种不好的做法,而不是泄漏(在JS等语言中很难产生实际的内存泄漏,除非有故意尝试或涉及浏览器错误)。@K3N:泄漏是指不再使用时不会释放的内存。这正好符合要求。认为在JS中很难进行内存泄漏的观点是错误的。