- - PR -
.NETでもメモリリーク?
1|2|3
次のページへ»
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2002-11-15 13:08
メモリリークと思われる現象がありました。
ArrayListを用意します。ここにデータをnewして放り込みます。すぐにClearメソッドでクリアします。しばらく待ちます。データをnewして放り込みます。すぐにClearメソッドでクリアします。・・・以下延々と繰り返し。 このプロセスをタスクマネージャで監視すると、メモリ使用量がどんどん増えます。1日動かし続けたところ、「何これ?」というほどメモリを使用していました。 ガベッジコレクションがいつ働くのかわかりませんが、やはり問題ではないでしょうか。それとも、Clearメソッドではメモリは解放されていないのでしょうか。
Services.exeがフリーズしてしまい、原因を探るためにタスクマネージャを起動すると、VB.NETでやるのが間違いといわれそうですが、VB.NETで作ったサービスのメモリ使用量がやたらと多くなるので、いろいろいじっているうちに、どうもこういうことらしいと判断しました。 また、Excelを起動してグラフを描かせようとしたのですが、こちらでも確認できました。
DrawGraphメソッド終了後、このアプリケーションとしてはxlsが参照しているメモリは破棄されるので、クラスExcelExecuteのFinalizeが呼ばれてExcelが落ちるだろうと期待していたのですが、20分くらい待っても落ちませんでした。ただし、アプリケーションを終了するとExcelも落ちます。また、アプリケーションは動かしたまま、エクセルだけ終了すると、以後、アプリケーションを使わずに起動するエクセルがおかしくなります。アプリケーションがエクセルを起動しようとすると例外が発生します(控えていません)。 Finalizeはガベージコレクタが動作するときに呼ばれると、どこかに書いてあったと思いますが、では、ガベージコレクタはどうなったら『参照されていない。ゴミである』と判断するのでしょう?また、自動変数にNewでインスタンスを割り当てた場合、変数を使わなくなる前にNothingを代入してやらなければならないのでしょうか。ASP.NETの説明ではNothingがほぼ必ず代入されているのですが、「CreateObject 関数」の説明では、『最後に、参照自体を解放します。』と書いてあるにもかかわらず、コードの最後には何もありません。それともVB.NETの問題で、C#では発生しないのでしょうか。 | ||||||||
|
投稿日時: 2002-11-15 13:47
Clearメソッドは参照をnullにするだけで、ガベコレはいつ働くかはわからないでしょう。 | ||||||||
|
投稿日時: 2002-11-15 16:54
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vbcon/html/vbconInitializationTerminationOfComponents.asp
この、リンクの説明のように、デストラクタはすぐには、働かないらしいですよ。 | ||||||||
|
投稿日時: 2002-11-15 17:08
.NETは使ってないから正確な話ではないんですけども
似たようなことをしているJavaでは、確か参照をnullで潰してもそのメソッドが終了しないとガベージコレクションの対象にならない、なんて話が「Effective Java」なんかに書いてあった記憶があります。 Javaと.NETじゃ違うとは思いますが、もしかしたら同じように開放したブロックとかメソッドを抜けないとダメってことがあるかもしれません、Whileの中身をそっくり別のメソッドに移して呼び出してみた場合はどうなりますでしょうか? もしかしたら同じような動きかも、と思っただけなんでうまくいくかは不明ですが。 | ||||||||
|
投稿日時: 2002-11-15 17:35
GC.Collectメソッドで強制的にガベージコレクションをさせて試してみるという手もありますね。
(.NETを使える環境に無いので自分で試せないのが残念) またfinalizeメソッドは呼び出されるとは限りませんので注意。 [ メッセージ編集済み 編集者: DaikiRyuto 編集日時 2002-11-15 17:36 ] | ||||||||
|
投稿日時: 2002-11-15 17:40
whileブロックの外で宣言されているものは、
whileブロック内で、clear()やnothingしても GCの対象にはならないと思います。 whileブロックが終了してから、nothingすれば、GC対象になるような気がします。(不確定ですが。…) あと、 >ガベージコレクタはどうなったら『参照されていない。ゴミである』と判断するのでしょう? ですが、このリンクにかかれています。 内容は、難しくて詳しくはわかりません。(すいませんです) http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpconautomaticmemorymanagement.asp | ||||||||
|
投稿日時: 2002-11-15 18:51
Clear()メソッドの後に、TrimToSize()メソッドを実行
してみてはどうでしょうか。 myArrayList.Clear() myArrayList.TrimToSize() Happy Programming! Akio Kasai | ||||||||
|
投稿日時: 2002-11-15 19:46
興味深い事例ですね.VB.NETは知りませんが,GCはLISPの世界で
古くから使われている技術であり,VB.NETだろうがJavaだろうが 所詮はLISPの真似に過ぎず,原理は同じはずです. >ガベージコレクタはどうなったら『参照されていない。ゴミである』と判断 >するのでしょう? 「そのインスタンスが到達可能でなくなった時」です. 到達可能というのは,まあ平たく言ってそのインスタンスへの参照を 間接又は直接に持っている場合です.ですから,ある参照に上書きしたり, その参照がスコープを抜けて無効になったりすれば,その時点でインス タンスはゴミであると判断することが可能になります. #以下のページが参考になるかと. #http://www.netgene.co.jp/java/technicalTerms.html#GC ただしGCは通常はlazyに実行されるため,ある程度メモリを圧迫する までは回収を実行しないのが普通です.このため回収されるタイミング は予測できません.即時回収も不可能ではないですが,それを保証する となるとパフォーマンスを犠牲にすることになるので,通常は行いません. GCがいつ動くかは不明だとは言え,通常はメモリを大量に消費する前には 実行されます.そうでないとGCの意味がありませんからね.メモリを大量に 消費しているにも関わらずGCが動いていないとなると,それはVMや標準 ライブラリのバグの可能性が極めて高いでしょう. ただし,GCは正常に動いていても,参照可能であるために回収できない という可能性もなくはないです.これについては,私はVB.NETの言語仕様 を知らないので全く分かりません. >ですが、このリンクにかかれています。 >内容は、難しくて詳しくはわかりません。(すいませんです) 要するに「インスタンスはヒープに作られる.GCとしては世代別GCを 使ってる.到達可能なインスタンスは回収されない」という程度の, ごく普通のことをMS地方の方言で書いてあるだけのようです. |
1|2|3
次のページへ»