- - PR -
継承したコントロールのメモリの解放
1|2|3|4
次のページへ»
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2009-01-20 13:47
いつもお世話になっております。
現在 VisualStudio.Net2005 の VB にて開発しています。 アプリを組み終わり実行しているとメモリリーク?の現象が出ました。 どこかで解放忘れがあるのかと思い、調べていたところ データセット(新規追加で作成できるデータセットです)のインスタンスを生成して、 解放しているつもりなのですが、そのメモリが解放されていない?ことが原因のようです。 さらに調べていくと、継承したコントロールでも同様の現象が確認できました。 以下にミニマムコードを記述しておきます。 ****************************************************************************** '単純にDataSetを継承しただけのカスタムDataSet Public Class CustomDataSet Inherits DataSet End Class '単純にLabelを継承しただけのカスタムLabel Public Class CustomLabel Inherits Label End Class 'ボタンによりテスト実行 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Debug.WriteLine(String.Format("{0:HH:mm:ss.fff} Start [{1:0}]", Now, GC.GetTotalMemory(False))) 'テスト的にループさせて生成→解放する For i As Integer = 0 To 1000000 '[ カスタムDataSetの場合 ] ************************************* Dim xLeak As CustomDataSet xLeak = New CustomDataSet xLeak.Dispose() xLeak = Nothing ''[ カスタムLabelの場合 ] ************************************ 'Dim xLeak As CustomLabel 'xLeak = New CustomLabel 'xLeak.Dispose() 'xLeak = Nothing ''[ 通常のDataSetの場合 ] ************************************ 'Dim xNoLeak As DataSet 'xNoLeak = New DataSet 'xNoLeak.Dispose() 'xNoLeak = Nothing ''[ 通常のLabelの場合 ] ************************************ 'Dim xNoLeak As Label 'xNoLeak = New Label 'xNoLeak.Dispose() 'xNoLeak = Nothing Next Debug.WriteLine(String.Format("{0:HH:mm:ss.fff} Before GC.Collect [{1:0}]", Now, GC.GetTotalMemory(False))) GC.Collect() Debug.WriteLine(String.Format("{0:HH:mm:ss.fff} End (GC.Collect) [{1:0}]", Now, GC.GetTotalMemory(True))) End Sub ****************************************************************************** 継承したコントロールの解放には何か特別な処理などが必要なのでしょうか? もしくは私のPCだけで起きる現象なのでしょうか? ちなみに VisualStudio.Net2003 で上記ミニマムコードを実行しても メモリは増えませんでした。 難しいかも知れませんが、よろしくお願いします。 | ||||
|
投稿日時: 2009-01-20 14:28
メモリが増えた減ったの判定はどうやってますか?
| ||||
|
投稿日時: 2009-01-20 14:40
ミニマムコード内の Debug.WriteLine にて出力しているもので判定しているのですが・・・。
逆にこれでは判断できないのでしょうか? | ||||
|
投稿日時: 2009-01-20 14:51
すみません。判定に何かツールを使ってると思い込んでいたのでコードをちゃんと読んでいませんでした。
もし、Dispose を呼び出したり、Nothong を代入することで、GCが実行されると考えられている場合は、これは違います。 また、GC.Collectを呼び出した場合は、確かにGCが実行されるのですが、これまたすぐに実行されるかどうかと言えば、CLRの気分次第です。 たとえば複数のプロセッサを使用していて、サーバー版CLRを使用していた場合は「真に併行」してGCが実行されたりします(確か)。 なので、そういうチェックはしないで、「GCをとりあえず盲信する」てのが一般的な落ち着きどころかと。 | ||||
|
投稿日時: 2009-01-20 15:06
コメントありがとうございます。
GCをとりあえず盲信しているのですが、いつまでたっても解放されないため。 OutOfMemoryException でお亡くなりになってしまいます。 ミニマムコードのループ件数を2桁ほど増やせば落ちてくれます。 VS2005からCLRの気分がよろしくないのでしょうかね(笑) 単純にControlを継承しただけでもダメでした。 標準コントロールのLabelなんかもColtrolを継承しているはずなのに、 こちらは現象が起こりません。 なにかがありそうな気がするのですが・・・。 | ||||
|
投稿日時: 2009-01-20 15:28
こんにちは。
DataSetの継承元のSystem.ComponentModel.MarshalByValueComponentクラスが ファイナライザを実装しているようですね。 だからGCで回収されにくくなっているんじゃないでしょうか? 「参考」 ガベージ コレクタの基本とパフォーマンスのヒント (ファイナライゼーションがガベージ コレクションに与える影響) ガベージコレクション入門: Microsoft .NET Framework の自動メモリ管理 Part I (完結化の内部メカニズム) | ||||
|
投稿日時: 2009-01-20 15:48
いや違ったかもしれません? MarshalByValueComponent.Dispose内で、GC.SuppressFinalize メソッドを呼び出しているようなので 完結キューにはエントリされないのかも!? | ||||
|
投稿日時: 2009-01-20 15:56
Tdnr_Symさんコメントありがとうございます。
ファイナライザの実装により、解放タイミングに違いが生じるということを 知らなかったので大変勉強になりました。 ですが、DataSetのほうはすぐに解放されるのに対し、 単純に継承したDataSetはすぐに解放されないというのは納得できません。 Tdnr_Symさんは継承元のソースを見られているようですが、 どこかで公開されているのでしょうか? |
1|2|3|4
次のページへ»