7

私はこのプレゼンテーションのスライドを見直していました: http://slid.es/gruizdevilla/memory

スライドの 1 つで、このコードはメモリ リークを引き起こすという提案とともに提示されます。

var buggyObject = {
   callAgain: function() {
     var ref = this;
     var val = setTimeout(function() {
        ref.callAgain();
     }, 1000);
   }
}

buggyObject.callAgain();
buggyObject = null;

誰かがここで問題をより詳細に説明できますか? ここでいくつかの微妙な点が欠けている可能性があります。

4

3 に答える 3

7

This is definitely a memory leak. However, the memory consumption is so small and cannot be measured. I did some small changes to the source code.

  • I put the entire code inside a loop to create the same scenario 100,000 times
  • I increased the timer interval to about 16 minutes. This prevents browser from crashing

Here is the code:

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;
}

Memory leak in Chrome

My experiment:

I ran the code in Chrome Version 34.0.1847.116 m and captured memory changes using Developer Tools\Timeline.

As we can see in the picture, around 32 MB of memory has been consumed for running this code and after a while it's been decreased to about 30 MB and stayed unchanged (see #1). After several garbage collecting attempts by Chrome (see #2) and one manual forced garbage collection by me (see #3, #4), the memory consumption remains unchanged. There is no more buggyObject and there is nothing we can do to release the memory. The only possible way is to close the browser.

What causes this?

The main reason for this behavior is the timer. Timer callback and its tied object, buggyObject will not be released until the timeout happens. In our case timer resets itself and runs forever and therefore its memory space will never be collected even if there is no reference to the original object.

于 2014-04-20T05:33:21.163 に答える
5

setTimeout() にメモリ リークがあるように見えるが、実際にはそうではないという別の質問があります。

ただし、著者が言おうとしているのは、buggyObject自分自身を呼び出す setTimeout を作成するため、buggyObject を equal に変更してもnull(オブジェクトの操作が完了し、クリーンアップできると言っています)、オブジェクトは削除されないということだと思います。 setTimeout() にまだ参照があるため、ガベージ コレクションが行われます。これは技術的にはメモリ リークです。setTimeout 関数への直接参照がなくなったため、後でクリアできます (ゾンビ タイムアウトのようなものです)。

于 2013-08-06T19:09:01.573 に答える