2011-12-12 18 views
11

メモリリークの原因になりますか?このコードはメモリリークの原因になりますか?

var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP 

for (var i=0 ; i< 1000 ; i++) 
{ 
    mc = new MovieClip() ; 
    mc.addEventListener(MouseEvent.CLICK , onClick) ; 
} 

これはどうですか?

for (var i=0 ; i< 1000 ; i++) 
{ 
    var mc:MovieClip ; //<<<<<<< INSIDE LOOP 
    mc = new MovieClip() ; 
    mc.addEventListener(MouseEvent.CLICK , onClick) ; 
} 

"removeEventListener"は上記のコードのいずれでも使用されていないため、両方ともメモリリークを引き起こしていると思います。

+1

1000個のムービークリップをクリック可能にする必要があるため、この時点ではメモリリークが発生しません。ムービークリップでやったことがあり、イベントリスナーの問題が再生されるようにそれらをメモリから削除したいときだけです。 Ascentionの答えは正しいが、「would」という言葉が重要である。 – crooksy88

+0

ここに誰もが訂正します。私は決してAdobeのドキュメンテーションを再び信用しません。私の更新された答えを見てください。私の現在の答えは間違っています。 –

答えて

6

あなたの1000のムービークリップには、あなたのonClick機能への参照があります。その逆ではありません。 あなたの質問に答えると、1000曲のムービークリップがGCedになるかどうかです。

一方、あなたのムービークリップのonClick関数への参照は、それが生きている(およびそれが属するかもしれない)オブジェクトを生かしています。これらのMCに他の参照情報があれば、それらを生き続けることができます。

次のコード:それはどんな強い参照を持っていないよう

mc.addEventListener(MouseEvent.CLICK , function(ev:Event):void{ trace("I am only a poor anonymous function"); }, false, 0, true); 

は、かなりすぐにあなたのリスナー関数GCedを持つことになります。あなたがあなたのステージに

stage.addEventListener(MouseEvent.CLICK, someObjectBelowIntheDisplayList.listenerFunction); 

をイベントリスナーを追加する場合は、trueにただし、useWeakReferenceを設定

はかなり関連する可能性がある上記のコードは、それが他の参照を持っていない場合でも、生きているあなたのリスナー関数でオブジェクトを維持します。

someObjectBelowIntheDisplayList.addEventListener(MouseEvent.CLICK, stage.onClick) 

上記のコードは、生きているあなたのsomeObjectBelowIntheDisplayListを保持しません。これは、ステージへの参照を持っていますが、ステージがsomeObjectBelowIntheDisplayListへの参照を取得していない

編集:このコードは明らかに私が言っているものをサポートしてい

import flash.display.MovieClip; 
import flash.events.Event; 

var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP 

function enterframe(ev:Event):void 
{ 
    for (var i=0 ; i< 1000 ; i++) 
    { 
     mc = new MovieClip() ; 
     mc.onClick = function(ev:Event){}; 
     // Use one of the following lines, comment out the other one 
     //mc.addEventListener(MouseEvent.CLICK , onClick) ; // no memory leak 
     stage.addEventListener(MouseEvent.CLICK, mc.onClick); // memory will rise up and up 
    } 
} 

this.addEventListener(Event.ENTER_FRAME, enterframe); 

function onClick(ev:Event):void 
{ 

} 

:MCを使用して、次のコードを試してみてください.addEventListenerはではありません。はメモリを消費します。それは私のシステムで約20MBのままです。 リスナー関数としてstage.addEventListenerを使用し、mc.onClickを使用すると、フレームごとにメモリ消費量が増加します。

+0

上記のテストコードでは、常にすべてのフレームに1000個のムービークリップが作成されます。メモリリークがあった場合、それらのオブジェクトはすべて収集されないため、メモリ消費量は**増加します。彼らはそうです。ムービークリップをステージにリスナーとして追加すると、メモリリークが発生します。参照は常に、ディスパッチャからリスナーに向かうものであり、他の方法ではありません。ディスパッチャーへの参照がもうなくなっても、それが何人のリスナーに関係なく破壊されます。 – Malyngo

+0

あなたは100%正直です。私は訂正した。私はより多くの情報で私の答えを更新しました。私がドキュメンテーションを最後に読んだときから、adobeが新しい情報を追加したようです。私は私の答えが間違っていると印を付け、クレジットがあなたに与えられるように求めました。 –

+0

何がENTER_FRAMEイベントを追加するのか。ループは十分ではありませんでしたか? –

6

更新、正解

私のオリジナルの答えが間違っていたと私は心からお詫び申し上げます。私は、私の思いやりのあるコメントと情報をそのまま残して、Adobeが何度も何度も信頼してくれることを永遠に思い起こさせるだろう。

"イベントリスナーが不要な場合は、removeEventListener()を呼び出すことで削除するか、メモリの問題が発生する可能性があります。ガベージコレクタはリスナーを削除しないため、イベントリスナーは自動的にメモリから削除されません。 (ディスパッチオブジェクトが存在する限り)(useWeakReferenceパラメータがtrueに設定されていない限り)。

イベントリスナーは、ディスパッチオブジェクトが最初に削除されている限り、弱い参照があるかどうかガベージコレクション天気です。したがって、これらの両方のケースでは、メモリリークが発生することはありません。私は私の答えを正しくチェックしないようにOPに依頼し、@マリンゴにクレジット/正解+アップフォートを与えます。

オリジナル(間違った)回答と(MIS)の情報が

どちらでしょうに従います。イベントリスナーをバインドすると元のオブジェクトへの強い参照が作成されるため、ガベージコレクタはそれをクリーンアップしません。イベントリスナーを明示的に削除するか、弱い参照として指定する必要があります。これはaddEventListenerのパラメータの1つでなければなりません。

「私たちのプレイヤーが死ぬことを想像して、我々は彼をしたい:リスナーが記事の

http://gingerbinger.com/2010/07/actionscript-3-0-events-the-myth-of-useweakreference/

概要を収集ごみであることから、他のオブジェクトを止めるつもりはないと主張し、人々のために

ただし、イベントリスナーは、ステージからプレーヤーへの参照を作成します。ステージは最上位の表示オブジェクトであり、常にアクセス可能であるため、マークスイーププロセスが実行されると、このイベントリスナーでガベージコレクタはホップfr他のすべてのリファレンスをクリアしてディスプレイリストから削除したとしても、プレイヤーオブジェクトのステージを変更する必要があります。

だから強く結合しただけでは、イベントリスナー少なくとも一つのシナリオは、まだを収集してからオブジェクトを防ぐことができます。

ベスト・プラクティス・ソリューション:

1)表示リストから削除します。
2)MovieClipの場合は、stop()を指示します。
3)オブジェクトが作成したイベントリスナーをすべて削除します。
4)親オブジェクトの参照をすべてnullに設定してクリアします。

を再度更新し

メモリリークは、必ずしもあなたがアプリケーションのメモリが継続的に成長が表示されますという意味ではありません。メモリリークは、リサイクルする必要があるときに、アプリケーションの存続期間中に割り当てられ、持続するメモリを簡単に記述することもできます。このテストコードのようなものは、あまり簡単に検出できません。しかし、これはN時間に1時間以上の長い試合で起こるようにしてください。私は一度書いた暗号化アルゴリズムで同じ状況が起こった。しばらくして、私のアプリは毎秒10フレーム以下で動き始めました。なぜなら、VMは実際にはもう使用していないメモリを使い果たしてしまったからです。

1

actionscriptはブロックスコープを持たないecmascript 3に基づいているため、どちらの例も同じです。

編集:ブロックスコープはありませんが、ActionScriptには機能スコープがあります。

メモリリークと同様に、オブジェクトはメモリ内にとどまります。

+2

"ブロックスコープはありません"はfalseです。スコープがメモリの割り当てと割り当て解除に関係していないということを意味するならば、それは別の話ですが、ブロックスコープ自体が存在しないと言うだけでは間違っています。 –

+0

ブロックスコープとして関数をカウントせず、それをスコープとして扱う限り、それは本当です。 (それはやはり技術的に真実です)。 – WORMSS

+6

私はJNissiと言いたいのですが、ループの内部または外部の変数を宣言するようにAS3を使用すると変数が異なります) – Patrick

関連する問題