- - PR -
.NETでもメモリリーク?
投稿者 | 投稿内容 | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2002-11-16 13:17
こんにちは。
GC関連の話題は、ついこの間、CSのMLで話題に上っていました。 GCについては、以下のMicrosoftのオンラインヘルプでも参考になるかと思います。 http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfsystemgcclasstopic.asp 参考までに。。。 | ||||||||||||||||||||
|
投稿日時: 2002-11-16 23:26
たくさんのご意見、ありがとうございます。職場では100Baseだけれど、自宅では息子の妨害&AirH"なのでなかなか見ることができず、1日でこんなについているとは驚きました。
さて、ご呈示いただいたURL(Operaだと表示が崩れる )も一通り目を通してみました。やはり、「自分で解放できない」というのは、私にとっては、とても大きな障害であると感じます。今回はWindowsServiceとして組んでいたため、それがいつの間にかGB!!(ほかのタスクよりもカンマが余分についていたことは確か)オーダーのメモリがアロケートされているのは納得できません。JAVAは使ったことはないですが、Web環境で使うという前提がありますよね?普通のアプリケーションとして、数日間にわたって実行しているわけではないものが、いつ動くかわからないガベージコレクタにメモリ破棄を任せても、それは終了すれば終わるのですから、かまわないと思います。しかし、WindowsServiceなど、長期間にわたって無休で動作するものがいつ破棄されるかわからないのでは、特にGBオーダーのメモリをアロケートしても(って、2GBまででしたよね、確か)さらにもっと要求する、しかもそのほとんどは開発者の意図ではすでに解放済みである、というのは、どうでしょう? (GC.CollectでGCが呼び出せるなら、結局FreeなりDeleteしているのと同じですよね) 所詮、「完全なものを提供するつもりはない」会社が作ったツールなので信用はしていませんが、それでも一定のレベルで信用しなければならないわけで、今回はそのわずかな信用さえ、失ってしまいそうです。(というか、これではプログラムできない!!)まぁ、私の周りでは、「所詮MSだから」ですべてが納得されてしまうのですが | ||||||||||||||||||||
|
投稿日時: 2002-11-17 00:15
> JAVAは使ったことはないですが、Web環境で使うという前提がありますよね?
確かにJavaはサーバサイド言語になってはいますね。後は携帯でゲームとか。 ただ、Javaの場合は間隔があまりないような無限ループを処理し続けるとある程度のところでメモリ関係のエラーになってアプリが落ちることがあります。落ちる方が良いのか落ちない方が良いのかはわかりませんが。 .NET(C#)でタスクトレイに常駐するアプリを開発しましたが、同じようにメモリ消費量の多さには呆れました。 起動で20MB使い、メモリ消費は下がることはありませんでした。GC、弱参照、null代入など色々と試しましたが、ほとんど効果は感じられませんでした。 そのアプリはタイマーで処理を行うのですが、処理が終わると24KB程度ずつメモリ消費量を増やしていく感じです。 苦肉の策で、メインになるFormを表示->最小化を行うと(タスクマネージャーで見る限り)メモリ消費量を2MB程度まで減らすことができるのを発見し、邪魔にならない部分でその処理を行っています。通常のアプリのウインドウを最小化するとメモリ消費量を減らせるのと同じ原理ですね。 この処理を起動時に行い、その後は最高で7MB程度でメモリ消費量は止まります。 やはり、常駐するアプリはインスタンス生成などの重い処理は最小限に抑えるなどの設計をきちんと行わないといけないみたいです。 | ||||||||||||||||||||
|
投稿日時: 2002-11-17 03:12
もしそれが結論であるならば、.NET FrameworkやJavaのような環境は諦めるしかありません。柔軟性を犠牲にして堅牢性を得ようとするのがこれらの共通の思想です。
その納得いかない状況が本当に対処不能なものであるのか、原因はどこにあったのかは把握されているのでしょうか?たとえば、GCの問題であるのなら、それを見るためのこんなツールもあります。パフォーマンスモニタもあります。
しかし、その意図を本当にCLRに正しく伝えられているでしょうか?それを調べるのが先決だと思いますが。GCはAIではありません。
そのわずかな信用はどうやって構築されたのですか?根拠のない信用が根拠もなく壊れるのは当然だと思いますが。
このコメントは、要するにこのスレにつけられた善意のコメントが参照している情報も、それらの方々が回答するにあたって考えられた基盤となっているものも、「所詮MSだから」無意味だということでしょうか。Jittaさんの周囲がどうであるかは存じませんが、それで済む話ならどうしてこの場に問題提起をされたのでしょうか。 | ||||||||||||||||||||
|
投稿日時: 2002-11-17 06:47
こんにちは。
ArrayList.Clear メソッド のヘルプの抜粋です。------------------------------- 解説 Count は 0 に設定されます。 Capacity は変更されません。 ArrayList の容量をリセットするには、 TrimToSize を呼び出すか、 Capacity プロパティを直接設定します。空の ArrayList に対して TrimToSize メソッドを使用すると、 ArrayList の容量は 0 ではなく、既定値に設定されます。 --------------------------------------------------------------------------- この説明から、ArrayListが確保したメモリーはClearメソッドでは開放されない 事が読み取れるのですが如何でしょうか。 EXCELのバージョンの方は、 Protected Sub Finalize() xlApp.Quit() End Sub xlApp.Quitは、EXCEL.Applicationオブジェクトが破棄可能になるだけです。 続けて、xlApp=Nothing を明示的に行った方が良いのではないかと推測します。 .NETとCOM(EXCEL)という2つのアーキテクチャーが混在する事象なので、 他にも考慮点があるかもしれません。 VB.NETを勉強し始めたばかりです。 誤解等ありましたら、ご指摘ください。 それでは。 [ メッセージ編集済み 編集者: リックス 編集日時 2002-11-17 06:48 ] | ||||||||||||||||||||
|
投稿日時: 2002-11-17 22:11
うーむ。 JavaのArrayListのclearメソッドは内部配列に対して全部nullを代入するので、ArrayListにつめられているオブジェクトは解放の対象となるはずですが(実装による?)、.NETでは違うのでしょうか………。 | ||||||||||||||||||||
|
投稿日時: 2002-11-17 22:48
> JavaのArrayListのclearメソッドは内部配列に対して全部nullを代入するので、
System.Collections.ArrayList.Clearも内部の配列にZeroMemoryを呼んでいるようなので、同じでしょう。ただし、 > ArrayListにつめられているオブジェクトは解放の対象となるはずですが そうとは限りません。ArrayListに入っているオブジェクトが他から参照されていなければ、という条件付きです。ですので、スレ頭のJittaさんのサンプルコードだけでは、メモリリークかどうかはなんとも判断できないのです。あのコードを実行してもメモリ使用量がどんどん増えたりしませんし。 | ||||||||||||||||||||
|
投稿日時: 2002-11-18 09:58
そうなんですか?!まぁ、ずいぶん削ってしまいましたから。。。 それで、金曜日のことですが、タスクマネージャで自作サービスのCPU使用率が上がったときにメモリ使用量が増え、CPU使用率が下がった後もそのまま、次の起動(5分後)でさらに使用量が増えるのを確認しています。それでデバッガにかけ、ArrayListに放り込んでいるところで増えているのを確認し、このArrayListを自動変数にしていたので「Clearしなくてもよいだろう」と思っていたのですが、何がどうなっているのかわからないのでとりあえずClearメソッドを追加しましたが、それでも下がらないことを確認しています。 他所で参照していないかと言うことについては、VB.NETは参照渡しは使わないのではないでしょうか?ByValなのでいちいちコピーして使っていると思っています。C++なら実行速度等を気にして参照渡しとかいろいろ気をつかいますが、メモリ周りのVB.NETの仕様がよくわかっていないので、「C++ならこうするのに」と思いながらも、そういうことはしないで作成しています。 ところで、関数内でNewしたものは関数を抜けたときに破棄されると理解しているのですが、それが間違っていますか? |