- PR -

継承したコントロールのメモリの解放

投稿者投稿内容
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2009-02-16 11:07
フィードバックを投げてみるとか。
http://connect.microsoft.com/VisualStudio

引用:

KT工房さんの書き込み (2009-02-16 10:48) より:

やはり動的にコントロールを作成するという作りがダメなんでしょうか?
それとも多少リーク?してもメモリの許容範囲内だから放置なんでしょうか?


作りがダメとは思いませんが、仰るような状況を考えると
・動的に作らずにすむのであれば、動的に作るのをやめる
・インスタンスを使い回しできるのであれば、使い回す
など、インスタンスの生成数をなるべく抑えるほうがよいのでしょうね。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2009-02-16 11:14
引用:

KT工房さんの書き込み (2009-02-02 13:28) より:
サンプルソースは以下です。

Dim lblTest as Label

For i as Integer = 1 to 10000000
lblTest = New Label()
lblTest.Dispose()
lblTest = Nothing
Next


私は .NET の Dispose はあまり良くは知らないのですが、これは Dispose をしたというマークを付けるだけであり、lblTest.Dispose() の次の行に実行が移った時点では、メモリーの解放のようなことがおこなわれるかどうかは保証されないものではないでしょうか。すなわち、ループで回すのでバックログがどんどん溜まるから、メモリー不足になるのではないでしょうか。
また、もし、この時点ですでにメモリーが解放されるとしたら、Dispose のコストが非常に高くなってしまい、現実的ではないと思います。

ループ中に Sleep などで待つようにしても、その内にメモリー不足になるのでしょうか。それかコントロールなので Sleep ぐらいではだめで、一旦、DoEvents 相当のことをしてメッセージポンプが動くようなことも要るのかもしれませんが。

#以下、追記します。

「Dispose をしたというマークを付けるだけ」と書きましたが、この書き方だとちょっと思っていることとニュアンスが違いました。

Dispose メソッドを呼んでも Dispose の処理を開始できるというマークを付けるだけであり、Dispose を開始するかどうかや Dispose が完了するかどうかは保証されないのではないでしょうか、と考えます。

[ メッセージ編集済み 編集者: unibon 編集日時 2009-02-16 11:26 ]
masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2009-02-16 13:13
引用:

unibonさんの書き込み (2009-02-16 11:14) より:

ループ中に Sleep などで待つようにしても、その内にメモリー不足になるのでしょうか。それかコントロールなので Sleep ぐらいではだめで、一旦、DoEvents 相当のことをしてメッセージポンプが動くようなことも要るのかもしれませんが。




label = nothing の後に Sleep(1) を追加すると、解放されるようですね。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2009-02-16 16:33
引用:

Dispose メソッドを呼んでも Dispose の処理を開始できるというマークを付けるだけであり、Dispose を開始するかどうかや Dispose が完了するかどうかは保証されないのではないでしょうか、と考えます。



どちらも違います。

Dispose() メソッドは「クラスインスタンスがカプセルしているアンマネージリソースの解放を行う」ためのメソッドです。

Dispose() メソッドはクラスインスタンス(の構築に使用されるマネージドなメモリ)の破棄をするものではありません。

Dispose() メソッド呼び出しによって何が解放されるのかは、個々のクラス実装に依存します。

ラベルコントロールの場合、Win32 のウィンドウハンドルの解放が行われます。

Label クラスのインスタンス構築に使用されたマネージメモリの解放はGC任せです。

Label クラスに限らず、GCによるマネージドメモリの回収よりも早いペースでインスタンス生成を行えば、メモリ不足となるのは明白です。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2009-02-16 16:34
引用:

label = nothing の後に Sleep(1) を追加すると、解放されるようですね。



「まじない」ですね。

そもそも label = nothing に意味ないし。

Sleep(1) の引数が 1 で常に期待する効果が得られる保証もありません。

実行環境の CPU 性能やコア数、搭載メモリ量などによってコロコロ変わり得ます。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
はにまる
ぬし
会議室デビュー日: 2003/12/19
投稿数: 969
お住まい・勤務地: 誤字脱字の国
投稿日時: 2009-02-16 22:08
前から気になっていたので質問です。
引用:

渋木宏明(ひどり)さんの書き込み (2009-02-16 16:34) より:

Sleep(1) の引数が 1 で常に期待する効果が得られる保証もありません。
実行環境の CPU 性能やコア数、搭載メモリ量などによってコロコロ変わり得ます。


逆に言い換えれば
iniファイル等でパラメタ化しマシン毎に応じた設定を可能とすれば効果があると考えていいのでしょうか?

.Netになってメモリ問題に頻繁に遭遇するようになり少々嫌気が指してきているのですが、以前CPU問題やメモリ問題の古典的な対策してSleep処理を思いだし、開発企業に対策を要求したところ2つの案件で成果がありました。

協力会社のやっている事なので詳細報告は求めていませんが、推測としてSleepを入れる事によりGCが動き易くなると考えています。.Netに強制的にGCを実行させるコマンドは無いと聞いています。であればSleep処理は実用的な手段として頭の片隅に置いておいてもいいと思うのですが如何でしょうか?
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2009-02-16 22:46
引用:

逆に言い換えれば
iniファイル等でパラメタ化しマシン毎に応じた設定を可能とすれば効果があると考えていいのでしょうか?



いいえ。

他プロセスの実行による CPU 負荷やメモリ使用状況などによっても、適切な値は変わるはずなので、静的に値を求めるのは難しいでしょう。

引用:

.Netになってメモリ問題に頻繁に遭遇するようになり少々嫌気が指してきているのですが、



GCの本来の狙いはメモリ管理の煩雑さからプログラマを解放することにあります。

ですが、.NET のGCは一般的なシナリオで高パフォーマンスが得られることを狙った設計になっているため、極端なシナリオではGCが間に合わないケースが起こります。

なので、.NET のGCで不都合を生じるシナリオでは、それに見合った設計が必要です。
実際、高負荷対策として構造体配列を自分で管理して使いまわすようなケースもあります。

引用:

協力会社のやっている事なので詳細報告は求めていませんが、推測としてSleepを入れる事によりGCが動き易くなると考えています。



逆じゃないかな?

メモリ消費のペースが落ちたので、結果としてGCによるメモリ回収が間に合ったんだと思います。

ただ、前回も今回も書きましたが、実行環境によってはまるで効果がないことも十分に考えられる処置です。

引用:

.Netに強制的にGCを実行させるコマンドは無いと聞いています。



いいえ、あります。

GC.Collect() がそれです。


[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2009-02-16 22:47 ]

[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2009-02-16 22:52 ]
Azulean
大ベテラン
会議室デビュー日: 2008/01/04
投稿数: 123
お住まい・勤務地: 大阪府
投稿日時: 2009-02-16 22:55
参考と言うことでリンクを張っておきます。
http://msdn.microsoft.com/ja-jp/library/system.gc_members.aspx

ファイナライザの完了を待つとかも一応あります。

スキルアップ/キャリアアップ(JOB@IT)