[英]How does setTimeout() create a memory leak in this code?
我正在查看本演示文稿中的幻燈片: http : //slid.es/gruizdevilla/memory
在其中一張幻燈片上,此代碼顯示了它會造成內存泄漏的建議:
var buggyObject = {
callAgain: function() {
var ref = this;
var val = setTimeout(function() {
ref.callAgain();
}, 1000);
}
}
buggyObject.callAgain();
buggyObject = null;
有人可以在這里更詳細地解釋這個問題嗎? 我可能在這里遺漏了一些微妙之處。
這絕對是內存泄漏。 但是,內存消耗如此之小,無法衡量。 我對源代碼做了一些小的改動。
這是代碼:
for (var i = 0; i < 100000; i++) {
var buggyObject = {
callAgain: function() {
var ref = this;
var val = setTimeout(function() {
ref.callAgain();
}, 1000000); //16m
}
}
buggyObject.callAgain();
buggyObject = null;
}
我的實驗:
我在Chrome 版本 34.0.1847.116 m 中運行代碼並使用 Developer Tools\\Timeline 捕獲內存更改。
正如我們在圖片中看到的,運行這段代碼消耗了大約 32 MB 的內存,一段時間后它減少到大約 30 MB 並保持不變(參見 #1)。 在 Chrome 嘗試多次垃圾回收(參見 #2)和我手動強制垃圾回收(參見 #3、#4)之后,內存消耗保持不變。 不再有buggyObject
並且我們無法釋放內存。 唯一可能的方法是關閉瀏覽器。
這是什么原因造成的?
這種行為的主要原因是計時器。 計時器回調及其綁定對象,直到超時發生才會釋放 buggyObject。 在我們的例子中,定時器會重置自己並永遠運行,因此即使沒有對原始對象的引用,它的內存空間也永遠不會被回收。
還有另一個問題描述了 setTimeout() 看起來如何有內存泄漏,但實際上並沒有。
但是,我認為作者想說的是,由於buggyObject
創建了一個調用自身的 setTimeout,即使您將 buggyObject 更改為等於null
(說您已完成該對象並且可以對其進行清理),該對象也不會'不會被垃圾收集,因為在 setTimeout() 中仍然有對它的引用。 這在技術上是內存泄漏,因為不再有對 setTimeout 函數的任何直接引用,因此您可以稍后清除它(如果您願意的話,這有點像僵屍超時)。
正如advncd 指出的那樣,計時器被執行並在堆棧上添加更多數據。 對發生的事情有一個概念性的看法:
var a = 123;
// call the setTimeout.function
var a = 123;
// call the setTimeout.function
var a = 123;
// call the setTimeout.function
var a = 123;
// call the setTimeout.function
var a = 123;
// call the setTimeout.function
var a = 123;
// call the setTimeout.function
var a = 123;
// call the setTimeout.function
var a = 123;
// call the setTimeout.function
var a = 123;
...etc...
因此,每次在永遠增長的堆棧上分配一個新變量a
。
然而,advncd 沒有提到的是,您有一個 setInterval() 函數來完成您需要做的事情:一遍又一遍地調用相同的函數。 現在你仍然有一個“內存泄漏”,但只有初始化參數泄漏(即它不會在每次計時器超時時增長。)
所以從概念上講,調用是平坦的,您可以避免泄漏:
a = 123;
// call the setTimeout.function
// call the setTimeout.function
// call the setTimeout.function
// call the setTimeout.function
// call the setTimeout.function
// call the setTimeout.function
// call the setTimeout.function
...etc...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.