- PR -

くだらない質問なんですが・・

投稿者投稿内容
eno
常連さん
会議室デビュー日: 2008/08/22
投稿数: 28
お住まい・勤務地: 代々木上原
投稿日時: 2008-08-25 13:06
レス遅れましてすみません。
理解の程度は私のほうが低いと思いますが、どちらもいっていることは正しい(ただ会話のが成立していない気がします。)

「ユーザ側でインスタンスの破棄ができない」から「フォームを破棄」で代替>>
フォームがクローズされていれば(この時点ではまだgcが働いてない)、そのうちgc側のタイミングでclose処理が行われるから、処理単位をフォーム単位であわせるようにすればかなり安全になると思います。(コードに書いてある以上、Mainフォーム側から可能性として呼び出すこともあると思います。エラーがハンドリングされないと予期せぬ動作をする)

大抵のフィールドはその宣言するクラスのインスタンスと必要な寿命が一致するでしょうけど。 >>
まぁ私自身メモリリークはかなり軽視したプログラミングをしています。。
Cではブロック単位を細かくしていればいいし、大抵はシステムやマシンの都合上、再起動が行われることも計算に入れてます。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-08-27 21:13
 なかなかおもしろいですね。「くだらない質問」って書いてあるから読んでなかったけど、おもしろいスレッドじゃないですか。

引用:

enoさんの書き込み (2008-08-25 13:06) より:
理解の程度は私のほうが低いと思いますが、どちらもいっていることは正しい(ただ会話のが成立していない気がします。)


いえいえ。あなたの理解が間違っていますよ。

 GC は、GC がマネージしているメモリのみ、面倒を見ます。Dispose や別名としての Close は、アンマネージなメモリの面倒を、開発者が見るために行います。

 Form を含め、画面上に表示されるコントロールは、すべて CreateWindow 関数<microsoft.com>を呼び出しています。この関数から返されるウィンドウ ハンドルが、「アン マネージド リソース」です。このリソースは、開発者が管理しなければなりません。この値を、Dispose によって破棄します。したがって、Dispose した後に ShowDialog メソッドを呼び出すと、例外が発生します(もしくは、暗黙のうちに CreateWindow 関数が実行される)。
 ところが、OpenFileDialog.FileName は、「マネージド リソース」です。これは、GC によって回収されるまで、参照可能です。このリソースは GC が管理していますので、ガーベッジ コレクションが回収するまで参照できます。

引用:

Hongliangさんの書き込み (2008-08-22 22:33) より:
.NET ではメモリの解放と Dispose や Close の呼び出しはまったく関係ありません(アンマネージドなメモリは除きますけど)。ですので言葉の綾などではなく明確に区別しなければならない問題です。
そして、GC はメモリ管理の機構であり、それ以外のリソース、ファイルハンドルであるとか GDI ハンドルであるとかは GC 自体は関知しません。


ということです。

  • GC が貸し出すメモリは、GC が管理するので放置する。
  • その他が取得するリソースは、IDisposable インターフェイスを実装して使用者に「Dispose をしなければならない」ことを通知し、Dispose によって解放する。

という使い分けが必要です。明確に使い分けなければならないので、
引用:

これは言葉のあやの問題だと思います。
メモリを解放するとか、disposeするとかcloseするとかfreeとかreleaseだとか言い方・表現の違いにすぎないです。
今回はメモリ解放のタイミングが主題で、どの言語でもそれ以外は変わらないはずです。


ということとは、「どちらもいっていることは正しい」とは言えません。Close, Free, Release は、Dispose の別名として定義してある場合は Dispose と同意で「表現の違い」と言えます。しかし、「GC によるメモリの解放」とは違います。


引用:

大抵はシステムやマシンの都合上、再起動が行われることも計算に入れてます。


 Vista ではスリープが推奨され、デフォルト設定になっていることをお忘れなく。
# そんなに頻繁に再起動が行われるなら、「49日問題」が発覚することもなかったよなぁ...とかつぶやいてみる。
eno
常連さん
会議室デビュー日: 2008/08/22
投稿数: 28
お住まい・勤務地: 代々木上原
投稿日時: 2008-08-29 14:52
要は、GC機能っていうのは誇大広告でほとんどのオブジェクトがアンマネージなメモリで生成されているということですか?画面上に表示されるコントロールすべてアンマネージなメモリ領域(スタック)に管理されているということですよね。

アンマネージなコードは、SDKのメソッドや、オーバライドメソッドや構造体などの一部であると思ってました。オブジェクトはファイルストリームとフォーム以外はアンマネージなメモリ確保だと思ってました。でなければ、実行時にメモリ容量を何十MBととらないと。。GC機能が貧弱だとすると、.netFWによるインタープリタではただハードウェアの違い、OSの違いを超えていくためのもの?後はSDKくらいか・・

Form を含め、画面上に表示されるコントロールは、すべて CreateWindow 関数<microsoft.com>を呼び出しています。>>
質問ですが、CreateWindow関数は Windows API 関数の一つであって、内部変換(call)の問題ではないですか?確かにそのWHはそのオブジェクトを一意に指し示すだけのアンマネージな数値だと思いますが。。
CreateWindow() 関数を使えば、ブラウザに部品としてついているような「ボタン」や「コンボボックス」、「ステータスバー」といったアイテムを、自分のプログラムでも使うことができますが、要は内部の仕組みの話では?

Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-08-29 22:41
 「誇大広告」って(^-^; 理解が及んでいないだけでしょう。
 マネージド アプリケーションの範囲では、メモリ リソースは全て、GC によってマネージされています。マネージされているから「Managed」です。逆に言うと、GC が管理するのは、数あるリソースのうち、メモリだけです。他のリソースは、管理しません。他のリソースを管理するために、IDisposable インターフェイスを継承して、開発者に「開発者が生存期間を管理しなければならないリソースを使っている」ことを、明示します。
 後先になりますが、「内部の仕組み」の話をすると、Basic Class Library で用意されているクラスに関しては、Dispose を呼び出さなくても、メモリ リソースが解放されるタイミングで Dispose も行われるように実装されています。
(参考:アンマネージ リソースをクリーンアップするための Finalize および Dispose の実装<microsoft.com>)

 「開発者が生存期間を管理しなければならないリソース」と書きました。GC は、いつメモリの回収を行うかわかりません。一応、GC にたいして回収を促すことはできますが、それを頻繁にしてはならないことが、MSDN ライブラリには書かれています。そのため、開発者が管理しなければならないリソースは、やはり GC に任せず、開発者が管理するべきでしょう。
(参考:ガベージ コレクションの強制実行<microsoft.com>)
 一つ誤解があると思うのは、開発者が管理しなければならないのは「メモリ」ではなく、「リソース」であるという点です。メモリはリソースの一つですが、メモリだけがリソースではありません。
 ご指摘のように、CreateWindow が返すのは、ただの数値です。しかし、考えても見てください。メモリ アドレスであっても、数値ですよ。また、数値であるとはいっても、配列の添え字については、少し違った注意を払うのではないでしょうか。HWND はいわば、配列の添え字です。また、ストリームについても、ストリームが入出力バッファとして用意するメモリは、マネージド メモリです。GC が管理しているので、これについては Dispose する必要はありません。Dispose しなければならないのは、Stream クラスがストリームを開いたときに持つ、ディスクリプタです。これはおそらく、ただの数値です。また、ストリームに対して排他制御を行っていれば、使用する必要がなくなったときにそれを解放してやらなければなりません。これも、Dispose するべきリソースです。XP や Vista といったクライアント OS が共有しているファイルにアクセスすれば、アクセス権を確保します。これもリソースの一つです。
 Hongliangさんが書かれているように、メモリ リソースは、「貴重ではないリソース」と言えるでしょう。昔に比べれば、確かに貴重ではありません。しかし、「1プロセスが同時にアクセスできるファイルの数」や、「データベースに同時にアクセスできる数」は、大変貴重なりソースです。ちょっと変わったところでは、.NET Framework 2.0 からの、SecureString クラス<microsoft.com>があります。この文字列は、Dispose によってメモリ上の文字列を別の値で上書きします。こういった「貴重なりソース」については、自動で回収されるのを待つのではなく、開発者が明示的に回収を指示します。そのためのマークが IDisposable インターフェイスであり、実行を指示するためのメソッドが Dispose です。
eno
常連さん
会議室デビュー日: 2008/08/22
投稿数: 28
お住まい・勤務地: 代々木上原
投稿日時: 2008-09-01 12:33
リソース管理の理解及ばず、、丁寧な説明ありがとうございます。
プログラミングの骨子(リソース管理)になる理解を自分の中で少し深められたかと思います。仮にアセンブラにおける変数名やレジスタ名にしてもリソースという概念で扱っていかなくてはならない、プログラムで優先順位や順番を与えていくという作業ということ・。・


GCといってもクラスライブラリに過ぎず、実行ファイル以外の・・・(インタープリタ!?)から定期的に呼び出されているcollect()で瞬間的にクラスに対するマネージドコードからの参照のみチェックしているという理解でよろしいですか?Dispose,closeなどはメモリ上のインスタンスを破棄するメソッドで、GCクラスとは無関係であるということ。マネージコード(GCが見ている範囲のメモリ領域にのっかるインスタンスなど)は、GCクラスの実行によってしか解決できないということ。・・ここで一つ疑念がわいたんですがw、openfileDialogクラスのリソース管理においては、破棄する場合、オブジェクト名.dispose();と用意されているメンバにdispose()があるんですが、確かこのスレの中ではそれは特別でマネージドコードなんだということだったとおもいますが、そもそもdispose()がgcと無関係でかつマネージドコードならばdispose()メソッドは、openfileDialogクラスのメンバには不要な気がするのですが、どうなんでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-09-03 21:49
引用:

実行ファイル以外の・・・(インタープリタ!?)から定期的に呼び出されているcollect()で瞬間的にクラスに対するマネージドコードからの参照のみチェックしているという理解でよろしいですか?


 .NET Framework で作成したプログラムは、配布するときこそ中間コードですが、実行する直前にネイティブ コードにコンパイルされます(Just In Time コンパイル)。
 GC については、私も浅くしか理解していませんが、「GC.Collect メソッドが呼び出されている」というのは、違うと思います。GC.Collect によって実行される何かが実行されている、だと思います。また、定期的に呼び出されてもいなかったと思います。足りなくなったときに初めて呼び出されていたと思います。

引用:

Dispose,closeなどはメモリ上のインスタンスを破棄するメソッドで、GCクラスとは無関係であるということ。


 「メモリ上のインスタンスを破棄」というのがよくわかりませんが、「GC クラスとは無関係」というのは、その通りです。私の理解では、Dispose は、「開発者が管理しなければならないリソースについて、使用期間終了を指示する」です。
 インターフェイスの命名規約のため、IDisposable「破棄できる」という名前になっていますが、使用するケースから考えると、「破棄しなければならない何かを持っている」インターフェイスです。先も取り上げた、SecureString クラスは、他のアプリケーションからメモリを覗き見られるのを防ぐため、Dispose メソッドでは、使用しているメモリを無意味な値で上書きします。この行為は、「確保したものを解放する」とは違います。しかし、パスワードを書き記したメモを破り捨てるなど、「破棄」であることに代わりありません。
 あるいは、「破棄」という言葉に問題があるのかもしれません。「借りていたものを返す」と理解する方が、よいのかもしれません。

引用:

openfileDialogクラスのリソース管理においては、破棄する場合、オブジェクト名.dispose();と用意されているメンバにdispose()があるんですが、確かこのスレの中ではそれは特別でマネージドコードなんだということだったとおもいますが、そもそもdispose()がgcと無関係でかつマネージドコードならばdispose()メソッドは、openfileDialogクラスのメンバには不要な気がするのですが、どうなんでしょうか?


 使い方によります。
 まず、「オブジェクト名.dispose();と用意されているメンバにdispose()がある」のではなく、「IDisposable インターフェイスを実装するクラスが、Dispose メソッドを実装している」です。もちろん、同名の IDisposable と関係ないメソッドを作成できますが、そうした場合は少し意味が異なってきます。もし、Dispose というメソッドを単独で作成した場合、Dispose しなければならないかどうかは、リフレクションによって Dispose というメソッドがあるかどうか調べることで判断しなければなりません。しかし、IDisposable インターフェイスを実装している場合、IDisposable にキャスト可能かどうかでDispose の必要があるかどうかを確認できます。


 多くの場合、Visual Studio を使用して、ツール メニューに並んでいる OpenFileDialog をフォーム上にドラッグ ドロップして使用していると思います。この場合、Dispose する必要はありません。OpenFileDialog は Control を継承しているので、Form の Controls に登録され、Form が Dispose されるときに Dispose されます。むしろ、明示的な Dispose はしてはいけません。

 そうではなく、何らかのメソッドの中で OpenFileDialog のインスタンスを生成した場合、そのメソッドを抜ける前に Dipose しておきます。
 OpenFileDialog のインスタンスを生成するために必要なメモリは、GC から借り受けて、GC に管理を任せます。しかし、OpenFileDialog というフォームを表示するために、カーネル(?)から借りたウインドウ ハンドルは、カーネルに返さなければなりません。
 多くの人が、「OpenFileDialog は、ウインドウ ハンドルを使っている」ということを知らないかもしれません。また、知らなくてもいいように、デザインされています。しかし、「返さなければならない何かを使っている」ことまで知らなくてもいいようにはできませんでした。そのため、IDisposable インターフェイスが用意されました。このインターフェイスは、「返さなければならない何か」を使うことを、開発者に教えるためのインターフェイスです。その「何か」の具体的なことまで知る必要はありません。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2008-09-03 23:19
一応つっこんでおくと、OpenFileDialogはDisposeしなくても大丈夫です。
ではなんでIDisposableなのか?というと、単にComponentを継承しているからです。

別にDisposeしても問題はなくてむしろコーディング的にはしておく方が良い部類だとは思いますが。

--追記
なんでDisposeしなくても大丈夫かというと、ダイアログが閉じた時点でアンマネージなリソースは破棄されるつくりになっているからです。
※OpenFileDialogなどがたまたまそういうつくりになっているだけです。

[ メッセージ編集済み 編集者: なちゃ 編集日時 2008-09-03 23:24 ]
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2008-09-04 00:20
こんばんは。

引用:

なちゃさんの書き込み (2008-09-03 23:19) より:
一応つっこんでおくと、OpenFileDialogはDisposeしなくても大丈夫です。
なんでDisposeしなくても大丈夫かというと、ダイアログが閉じた時点でアンマネージなリソースは破棄されるつくりになっているからです。



私が躊躇して言えなかったことを、言っていただいてありがとうございます。

OpenFileDialogクラスが単に、Windows APIのGetOpenFileName関数のラッパーであることが分かっていれば、Disposeをしなくても動作的に問題ないことは分かるはずなんですが、
わざわざWindows APIの話を持ち出すのも野暮かと思いためらっていました。

あと質問者さんを責めるつもりはありませんが、質問者さんの投稿内容があまりにも、つっこみどころが多すぎて…

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