読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

IE7のメモリリーク問題

JavaScript

IE7には、以下の条件を満たす場合メモリリークが発生する問題があります。

  • DOMエレメントとJSオブジェクトが循環参照している
  • 上記エレメントをスクリプトで削除する

IE8では改修されているようでこの問題は発生しません。また、Firefox 3でも発生しません。

循環参照とメモリリークの例

function test1() {
  // DOMエレメントとJSオブジェクトの循環参照の例。
  // IE6ではこれだけでリークが発生したらしいが、IE7以降では発生しない。
  var largeData = createLargeData();
  var div = document.getElementById("div"); // DOMエレメント
  div.foo = function() {}; // JSオブジェクト
                            // closureにより、このオブジェクトはdiv,largeDataの参照を保持する。
                            // →JSオブジェクトとDOMエレメントの循環参照が発生。
}

function test2() {
  // IE7でリークが発生するパターン。複数回実行するとリークが発生する。
  // 以下のように循環参照したエレメントがスクリプトで破棄され、アンロード時に存在しないとGCの対象にならない。
  var largeData = createLargeData();
  document.getElementById("div").innerHTML = "<div id='created'>created</div>"; // 循環参照したままドキュメントから削除。
  var created = document.getElementById("created");
  created.foo = function() {};

  // IE8ではこの問題は改修されており発生しない。Firefoxでも発生しない。
}

確認はこちらIE7でtest2のリンクをクリックしていると、使用メモリががしがし増えていきます。IE8,Firefoxでは問題なし。

リークを探す

この問題は「Javascript Memory Leak Detector」で検出できます。

Javascript Memory Leak Detector

使い方は↑のサイトを参照。例で示したページを検証にかけると以下のような感じでリークが見つかるはず。

対策

で、対策ですが、「削除する前に循環参照を切る」とか「そもそも循環参照させない」とかでOK。

function fix1() {
  // リークを回避するためには、削除の前に参照を切ってやればOK。
  var largeData = createLargeData();
    
  var created = document.getElementById("created");
  if (created) delete created.foo; // 循環参照を切る。
    
  document.getElementById("div").innerHTML = "<div id='created'>created</div>";
  var created = document.getElementById("created");
  created.foo = function() {};
}

function fix2() {
  // そもそも循環参照させない。
  (function(){
    var largeData = createLargeData();
    document.getElementById("div").innerHTML = "<div id='created'>created</div>";
    return document.getElementById("created");
  })().foo = function() {};
}

確認はこちら