スレッド: [csharpll:0314] <教> リソース開放のタイミング

スレッド

[csharpll:0314] <教> リソース開放のタイミング

[ | ▲ / | ]
Subject:
[csharpll:0314] <教> リソース開放のタイミング
From:
FUKUDA, Fumiki <fukuda.fm@...>
Date:
Mon, 20 Mar 2006 15:21:09 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1506
Message-Id:
<083201c64be6$7b0abb60$e5d2060a‐at‐stf.ncos.nec.co.jp>
επιστημηです。

すんません、基本的なこと確認させてくださいませ。
C#では(.NETならなんでもいいけど)、メモリの開放はガベコレ時に
行われますけど、メモリ以外のリソースは何時開放されるんでしょか?

たとえば:
 StreamWriter sw = System.IO.File.CreateText("ほげほげ");
 sw.WriteLine("うにゃうにゃ");
 ...

こんなとき、ファイルがクローズされるのは何時なんでしょか?
デストラクタ内で後始末(Close)してるなら、
ガベコレ直前にデストラクタが動いて…ことになるんすか?

裏を返せばガベコレなんて何時動くかわかったもんじゃないから、
確実にClose()したいなら明示的にClose()を呼べ。ってことでしょか。

あるいはデストラクタ内でCloseしてるんなら、using(...)で囲んで
おけばスコープ外れるときにDisposeされ、そこでデストラクタが呼ばれて
めでたくCloseなのかな?

いや、Javaのときも感じたんだけど、
「ガベコレあるから散らかしっぱなしにできて楽ちん」
ってのは"うそっぱち"ですよね? 少なくともメモリ以外のリソース
を使ったんならプログラマが責任もってお片づけしたらんと。

とかなんとか考えてると"C++と大差ないぢゃん"て思ふ。
# んー、まだまだ.NETオンチだ orz

[csharpll:0315] Re: <教> リソース開放のタイミング

[ | / | ]
Subject:
[csharpll:0315] Re: <教> リソース開放のタイミング
From:
Imabeppu <imabeppu@...>
Date:
Mon, 20 Mar 2006 15:38:47 +0900
X-Mailer:
Becky! ver. 2.24.02 [ja]
Message-Id:
<20060320153150.8478.IMABEPPU‐at‐jp.fujitsu.com>
In-Reply-To:
314
References:
314
Imabeppu です。

Quoted from
Subject: [csharpll:0314] <教> リソース開放のタイミング
From: "FUKUDA, Fumiki" <fukuda.fm@...>
Date: 2006/03/20 15:21:09 (Mon, 20 Mar 2006 15:21:09 +0900)

> 裏を返せばガベコレなんて何時動くかわかったもんじゃないから、
> 確実にClose()したいなら明示的にClose()を呼べ。ってことでしょか。
:
> あるいはデストラクタ内でCloseしてるんなら、using(...)で囲んで
> おけばスコープ外れるときにDisposeされ、そこでデストラクタが呼ばれて
> めでたくCloseなのかな?

 finally で明示的に Close() を呼ぶか、using を使う必要があった
 と思います。

> いや、Javaのときも感じたんだけど、
> 「ガベコレあるから散らかしっぱなしにできて楽ちん」
> ってのは"うそっぱち"ですよね? 少なくともメモリ以外のリソース
> を使ったんならプログラマが責任もってお片づけしたらんと。

 GC があるけど、デストラクタは C++ と同じようなタイミングで呼び
 出される言語があるとうれしいです。参照オブジェクトは、参照カウ
 ンタが 0 になるときですね。

 C++ のデストラクタって、なにかと便利ですよね。JAVA や C# でこ
 れが使えないことで、なんだか退化したように思えるときがあります。

 GC の仕組みはよく知らないのですが、参照カウンタが 0 になったと
 きに「削除していいよ」というフラグを立てておいて、それらを GC
 で片付けるということではないのでしょうか? そうならば、削除フラ
 グを立てるときにデストラクタを呼び出してくれればいいのに、と思
 ってしまいます。そう簡単にもいかないんでしょうね。(^^;)



 # 「リソース開放のタイミング」→「リソース解放のタイミング」


--
|=====  ∧ ∧  =====  Imabeppu  =========================|
|==  n(=⌒o⌒=)n  ==  http://homepage3.nifty.com/bep/  ==|

[csharpll:0316] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0316] Re: <教> リソース解放のタイミング
From:
FUKUDA, Fumiki <fukuda.fm@...>
Date:
Mon, 20 Mar 2006 15:51:28 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1506
Message-Id:
<084401c64bea$b6d60e70$e5d2060a‐at‐stf.ncos.nec.co.jp>
References:
314 315
επιστημη@解放だ解放 です。

>   finally で明示的に Close() を呼ぶか、using を使う必要があった
>   と思います。

んむ。using(...) はデストラクタがちゃんと後始末(Close)して
くれてれば、って但し書きがつくんだろな。

>   C++ のデストラクタって、なにかと便利ですよね。JAVA や C# でこ
>   れが使えないことで、なんだか退化したように思えるときがあります。

C#にはあるみたいやけど > デストラクタ

>   GC の仕組みはよく知らないのですが、参照カウンタが 0 になったと
>   きに「削除していいよ」というフラグを立てておいて、それらを GC
>   で片付けるということではないのでしょうか? そうならば、削除フラ
>   グを立てるときにデストラクタを呼び出してくれればいいのに、と思
>   ってしまいます。そう簡単にもいかないんでしょうね。(^^;)

参照カウントで済むんなら楽なんだろけど、循環参照してたら
いつまでも成仏できずに三途の川のこっち岸でウロウロしてな
ならんし。

// 成仏できない双子の姉妹
リンリン.相方 = ランラン;
ランラン.相方 = リンリン;
// リンリン・ランランのわからんヒトは
// 叶恭子と叶美香に差し替えるが吉

せやけどふつーにアプリ書いてると参照カウントで大概間に合うっつー。

[csharpll:0318] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0318] Re: <教> リソース解放のタイミング
From:
Imabeppu <imabeppu@...>
Date:
Mon, 20 Mar 2006 16:07:15 +0900
X-Mailer:
Becky! ver. 2.24.02 [ja]
Message-Id:
<20060320160550.8481.IMABEPPU‐at‐jp.fujitsu.com>
In-Reply-To:
316
References:
315 316
Imabeppu です。

Quoted from
Subject: [csharpll:0316] Re: <教> リソース解放のタイミング
From: "FUKUDA, Fumiki" <fukuda.fm@...>
Date: 2006/03/20 15:51:28 (Mon, 20 Mar 2006 15:51:28 +0900)

> >   finally で明示的に Close() を呼ぶか、using を使う必要があった
> >   と思います。
>
> んむ。using(...) はデストラクタがちゃんと後始末(Close)して
> くれてれば、って但し書きがつくんだろな。

 Dispose ですね。

> >   C++ のデストラクタって、なにかと便利ですよね。JAVA や C# でこ
> >   れが使えないことで、なんだか退化したように思えるときがあります。
>
> C#にはあるみたいやけど > デストラクタ

 あるにはあるんですけど、using 使わないと呼び出されるタイミング
 が C++ と違うので、C++ ほど使えないという印象です。

> 参照カウントで済むんなら楽なんだろけど、循環参照してたら
> いつまでも成仏できずに三途の川のこっち岸でウロウロしてな
> ならんし。

 なるほど。
 GC の仕組み上でも、オブジェクトが削除可能になったかどうかは、
 削除可能になった瞬間には判明していないのかもしれませんね。適当
 なタイミングで調べてみると、「おー、これも削除してよいではない
 か」という感じでしょうか。

>  // 成仏できない双子の姉妹
:
>  // リンリン・ランランのわからんヒトは
>  // 叶恭子と叶美香に差し替えるが吉

 実際、叶姉妹は永久に生きていそうな気はします。(^^;)


--
|=====  ∧ ∧  =====  Imabeppu  =========================|
|==  n(=⌒o⌒=)n  ==  http://homepage3.nifty.com/bep/  ==|

[csharpll:0320] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0320] Re: <教> リソース解放のタイミング
From:
FUKUDA, Fumiki <fukuda.fm@...>
Date:
Mon, 20 Mar 2006 16:15:34 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1506
Message-Id:
<086601c64bee$151cdab0$e5d2060a‐at‐stf.ncos.nec.co.jp>
References:
315 316 318
επιστημη@どもども です

> > C#にはあるみたいやけど > デストラクタ
>
>   あるにはあるんですけど、using 使わないと呼び出されるタイミング
>   が C++ と違うので、C++ ほど使えないという印象です。

そかそか「スコープ外れたら直ちに起動」じゃないか。
「GCのついでに」なんだな。
ヘタすりゃ「一度も呼ばれずFinalizeのし」だし。

>   GC の仕組み上でも、オブジェクトが削除可能になったかどうかは、
>   削除可能になった瞬間には判明していないのかもしれませんね。適当
>   なタイミングで調べてみると、「おー、これも削除してよいではない
>   か」という感じでしょうか。

だと思う。ヒモの先をたぐってたぐって…ってやってんじゃないかしら。

>   実際、叶姉妹は永久に生きていそうな気はします。(^^;)

仙人だな。CoQ10が効いてんだろか。

[csharpll:0327] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0327] Re: <教> リソース解放のタイミング
From:
Tietew <tietew@...>
Date:
Mon, 20 Mar 2006 17:55:59 +0900
X-Mailer:
Becky! ver. 2.23 [ja]
Message-Id:
<20060320175458.34F8.TIETEW‐at‐tietew.net>
In-Reply-To:
318
References:
316 318
On Mon, 20 Mar 2006 16:07:15 +0900
In article <20060320160550.8481.IMABEPPU@jp.fujitsu.com>
[[csharpll:0318] Re: <教> リソース解放のタイミング]
Imabeppu <imabeppu@...> wrote:

> > >   C++ のデストラクタって、なにかと便利ですよね。JAVA や C# でこ
> > >   れが使えないことで、なんだか退化したように思えるときがあります。
> >
> > C#にはあるみたいやけど > デストラクタ
>
>   あるにはあるんですけど、using 使わないと呼び出されるタイミング
>   が C++ と違うので、C++ ほど使えないという印象です。

アレはデストラクタと呼ばれているけど実体はファイナライザです。
GCが開放するときにしか呼ばれません。



—[ Tietew ]——————————————————————————
メ : tietew@... / tietew@... / tietew@...
ホペ: http://www.tietew.net/     Tietew Windows Lab.
     http://www.masuclub.net/   鱒倶楽部
指紋: 26CB 71BB B595 09C4 0153  81C4 773C 963A D51B 8CAA

[csharpll:0328] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0328] Re: <教> リソース解放のタイミング
From:
Kouji Suzuki <k@...>
Date:
Mon, 20 Mar 2006 18:01:07 +0900
X-Mailer:
Microsoft Outlook IMO, Build 9.0.6604 (9.0.2911.0)
Message-Id:
<LNEFLJOMMEELLFMOGANPOEJJDOAA.k‐at‐kekyo.net>
In-Reply-To:
316
kekyo@お久しぶりです。

> C#にはあるみたいやけど > デストラクタ

C#のデストラクタは構文上はC++のデストラクタと同じですが、
コンパイルすると Finalize() になります。

ファイナライザ(とDispose)の実装がJavaと違ってややこしく
感じるのは、アンマネージリソースの制御を支配できるからです。

Dispose()が明示的に呼び出された場合、そのクラス内で暗黙に
(有効な)他のオブジェクトへの参照を保持しているか、
あるいは全く保持していないので、Dispose()の実装は安全に
動作することができます。

しかし、Finalize()内ではもはやクラスで保持している参照は
無効となっている可能性があるため、うかつに操作出来ません。

#なんだったか、そこで無効な参照を操作すると例外が出た
#ような気がしますが未確認。

では、Finalize()では何もできないのかというとそうではなく、
無効な参照さえ使用しなければ、アンマネージリソースの解放が
出来ます。
たとえば、IntPtr型で保持した値は参照ではなく値型なので
これを使って解放できます。

#ファイルハンドル類とかメモリのハンドルはIntPtrに入って
#いるので、CloseHandle() みたいなことをすればよい。

この問題とDispose()の実装をうまくするために、プログラミング
..NET Framework P.475で示されるような実装を行うことを
推奨しています。

Dispose()は明示的に呼び出さない限りは、GCが呼び出すことは
ありません(C#ではusingのブロックを出るときにDispose()を
呼び出すfinalizeを生成できるけど同じです)。

GCがIDisposableを実装していることを検知して、自動的に
Dispose()を呼び出してくれれば良いのに、と思ったことも
ありますが、以上のような理由で

「そのタイミングでDispose()が呼ばれても困ったチャンになる」

ためにそうなっていないのだと思います。

> GC が働く前にプロセスが終了してしまう場合などはファイナライザ
> が呼び出されることは保証されていないはずです。

これ、私も必ず呼び出されると思っていたのですが、
実際は呼び出されないことがありました。
OSのプロセスが終了する場合は、OS自身がアンマネージ
リソースを解放できるからだと思っています。

私もC++のようにデストラクタを活用したい口なので、
しかたなくusing書きまくってます。

> いや、Javaのときも感じたんだけど、
> 「ガベコレあるから散らかしっぱなしにできて楽ちん」
> ってのは"うそっぱち"ですよね? 少なくともメモリ以外のリソース
> を使ったんならプログラマが責任もってお片づけしたらんと。

禿同禿同 :-)
結局、ちゃんとコントロールすることが大事だし、
そうせざるを得ないです。

ちなみに、2.0ではまた調べてませんが、ADO.NETの実装で
DBへの接続のClose()とDispose()は意味合いが異なるので
注意が必要です。

#どうせならICloseableを作ったほうが良かったのではと。

----------------------
Kouji Suzuki / Microsoft Certified Professional
mailto:k@...
# 実行形式の添付ファイルかHTMLメールは自動的に廃棄されます。
# It will be automatically discarded if the attached file of
# executable files or "HTML mail" is transmitted to this mail address.

[csharpll:0329] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0329] Re: <教> リソース解放のタイミング
From:
Kouji Suzuki <k@...>
Date:
Mon, 20 Mar 2006 18:03:42 +0900
X-Mailer:
Microsoft Outlook IMO, Build 9.0.6604 (9.0.2911.0)
Message-Id:
<LNEFLJOMMEELLFMOGANPEEJKDOAA.k‐at‐kekyo.net>
In-Reply-To:
328
訂正。

> しかし、Finalize()内ではもはやクラスで保持している参照は
> 無効となっている可能性があるため、うかつに操作出来ません。
>
> #なんだったか、そこで無効な参照を操作すると例外が出た
> #ような気がしますが未確認。

上記はデバッガで確認したもので、実際にはFinalize()で発生した
例外はGCでにぎりつぶされます。

----------------------
Kouji Suzuki / Microsoft Certified Professional
mailto:k@...
# 実行形式の添付ファイルかHTMLメールは自動的に廃棄されます。
# It will be automatically discarded if the attached file of
# executable files or "HTML mail" is transmitted to this mail address.

[csharpll:0330] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0330] Re: <教> リソース解放のタイミング
From:
FUKUDA, Fumiki <fukuda.fm@...>
Date:
Wed, 22 Mar 2006 10:44:06 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1506
Message-Id:
<0a8801c64d52$1dff5e90$e5d2060a‐at‐stf.ncos.nec.co.jp>
References:
329
επιστημηです。

まとめてみる。間違いあったら突っ込んでおくんなさい。

- C++
 auto: スコープから外れたらデストラクタ X::~X() が'必ず'動く。
 heap: 明示的にdeleteされたらX::~X() が'必ず'動く

- C++/CLI(managed)
 auto: スコープから外れたらデストラクタ X::~X() が'必ず'動く。
 heap: GC直前にデストラクタX::~X()が動く。が、GCされずに終了する
 こともアリ。そんときゃファイナライザX::!X()が(あれば)動く。
 なのでデストラクタX::~X()はその中でファイナライザX::!X()を呼び、
 デストラクタ/ファイナライザは'何度呼ばれてもコケないように'
 実装すべし。

- C#
 auto: なにそれ? おいしいの?
 heap: 確実に動く(C++でいう)デストラクタはない。
 X::~X()は実はファイナライザ。確実に後始末を行いたければ、
 プログラマが明示的に後始末メソッドを呼び出す(finally節で呼ぶが吉)。
 もしくはIDisposableを実装し(void Dispose() 内で後始末を行い)、
 usingでくるんでおく。ただし、Disposeが呼ばれてもインスタンス
 (つかメモリ領域)はGCまで居座ってる。 

[csharpll:0331] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0331] Re: <教> リソース解放のタイミング
From:
FUKUDA, Fumiki <fukuda.fm@...>
Date:
Wed, 22 Mar 2006 10:50:16 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1506
Message-Id:
<0a9201c64d52$f8400500$e5d2060a‐at‐stf.ncos.nec.co.jp>
References:
329 330
επιστημηです。補足。

> - C++/CLI(managed)
>   auto: スコープから外れたらデストラクタ X::~X() が'必ず'動く。
>   heap: GC直前にデストラクタX::~X()が動く。が、GCされずに終了する
>   こともアリ。そんときゃファイナライザX::!X()が(あれば)動く。
>  なのでデストラクタX::~X()はその中でファイナライザX::!X()を呼び、
>  デストラクタ/ファイナライザは'何度呼ばれてもコケないように'
>  実装すべし。

  heapの場合、GCされるのを待たずとも明示的にdeleteすることで
  デストラクタを確実に呼び出すことができる。たとえそうしても、
  GC(メモリ解放)がその場で行われるわけではないけども。

[csharpll:0332] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0332] Re: <教> リソース解放のタイミング
From:
Satoshi Nakamura <ml@...>
Date:
Wed, 22 Mar 2006 18:58:37 +0900
X-Mailer:
QMAIL 2.9.21.2899 / Windows XP Service Pack 2 / x86
Message-Id:
<379220060322095837ml‐at‐snak.org>
In-Reply-To:
330
References:
329 330
中村です。

At 22 Mar 2006 10:44:06 +0900 FUKUDA, Fumiki wrote:
> - C++/CLI(managed)
>   auto: スコープから外れたらデストラクタ X::~X() が'必ず'動く。
>   heap: GC直前にデストラクタX::~X()が動く。が、GCされずに終了する
>   こともアリ。そんときゃファイナライザX::!X()が(あれば)動く。
>  なのでデストラクタX::~X()はその中でファイナライザX::!X()を呼び、
>  デストラクタ/ファイナライザは'何度呼ばれてもコケないように'
>  実装すべし。

C++/CLIでは、~X()はIDispose::Dispose()と、!X()はFinalize()と(ほぼ)同義で
す(「ほぼ」と書いたのは親クラスのメソッドを自動的に呼び出してくれるかどう
かが異なるためです)。

よって、~X()は明示的に呼び出されない限り呼び出されることはありません(GCの
過程では呼び出されません)。呼び出す方法は二つあり、一つ目はauto変数として
宣言する方法です。この場合、スコープから外れたときに呼び出されます(C#の
usingと同じ)。もう一つは、明示的にdeleteする方法です。

!X()はファイナライザなのでGCの過程で呼び出されますが、AppDomain自体が終了
するような場合には呼び出されないこともあります。

Finalize()(!X())の中からDispose()(~X())を呼び出すことはできますが、多
くの場合メリットよりデメリットの方が大きいことが多いのでよく考えてからやっ
た方が良いと思います。

--
Satoshi Nakamura <snak@...>

[csharpll:0333] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0333] Re: <教> リソース解放のタイミング
From:
FUKUDA, Fumiki <epi-@...>
Date:
Fri, 24 Mar 2006 02:33:30 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2900.2180
Message-Id:
<00d901c64e9f$e8ecfdd0$0f00a8c0@epi1st>
References:
329 330 332
επιστημηです。

>> - C++/CLI(managed)
>>   auto: スコープから外れたらデストラクタ X::~X() が'必ず'動く。
>>   heap: GC直前にデストラクタX::~X()が動く。が、GCされずに終了する
>>   こともアリ。そんときゃファイナライザX::!X()が(あれば)動く。
>>  なのでデストラクタX::~X()はその中でファイナライザX::!X()を呼び、
>>  デストラクタ/ファイナライザは'何度呼ばれてもコケないように'
>>  実装すべし。
>
> C++/CLIでは、~X()はIDispose::Dispose()と、!X()はFinalize()と(ほぼ)同義で
> す(「ほぼ」と書いたのは親クラスのメソッドを自動的に呼び出してくれるかどう
> かが異なるためです)。

子::!子()されたとき、親::!親()は呼ばれないってことですか?
それともC#では子.Finalize()時に親.Filenalize()されないけど、
C++/CLIではやってくれるってことすか?

> よって、~X()は明示的に呼び出されない限り呼び出されることはありません(GCの
> 過程では呼び出されません)。呼び出す方法は二つあり、一つ目はauto変数として
> 宣言する方法です。この場合、スコープから外れたときに呼び出されます(C#の
> usingと同じ)。もう一つは、明示的にdeleteする方法です。

ぢっけんしました。

ref class X {
public:
 ~X() { assert(false); }
 !X() { System::Console::WriteLine("!"); }
};

int main() {
 X^ r;
 for ( int x = 0; x < デカい値; ++i )
   r = gcnew X();
}

…ホントだー、!するけど~しないや。

--- : ------ : ------ : ------ : ------ : ---
FUKUDA, (episteme) Fumiki
magical, but never a magic....

[csharpll:0334] Re: <教> リソース解放のタイミング: まとめ

[ | / | ]
Subject:
[csharpll:0334] Re: <教> リソース解放のタイミング: まとめ
From:
FUKUDA, Fumiki <epi-@...>
Date:
Fri, 24 Mar 2006 02:49:11 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2900.2180
Message-Id:
<00e201c64ea2$1801fdd0$0f00a8c0@epi1st>
References:
329 330
επιστημηです。 再度まとめ←まだ間違ってたりして ^^;;;

- C++
auto: スコープから外れたらデストラクタ X::~X() が'必ず'動く。
heap: 明示的にdeleteされたらX::~X() が'必ず'動く

- C++/CLI(managed)
auto: スコープから外れたらデストラクタ X::~X() が'必ず'動く。
heap: 明示的にdeleteされたらX::~X()が'必ず'動く。 # ここまでC++と同じ
 ただしdeleteしたからといって即座に解放されるわけじゃない。
 deleteせずに放っとくと、GC時にファイナライザX::!X()が(あれば)動く。
 が、X::!X()が呼ばれず終いになることもある(AppDomainが落ちたときとか)。
 なので確実な後始末をやりたきゃX::~X()で後始末し、インスタンスをautoに
 取るか、もしくはheapに取ったんなら明示的にdeleteすべし。これがC#での
 "usingでくるむ"のに相当する。
 # 後始末をX::!X()で行うテもあるが、そんときゃX::~X()内でX::!X()するが吉。
 # (X::!X()は何度呼ばれてもコケぬように書け)←この但し書きは正しい?

- C#
auto: なにそれ? おいしいの?
heap: 確実に動く(C++でいう)デストラクタはない。
 X::~X()は実はファイナライザ。確実に後始末を行いたければ、
 プログラマが明示的に後始末メソッドを呼び出す(finally節で呼ぶが吉)。
 もしくはIDisposableを実装し(void Dispose() 内で後始末を行い)、
 usingでくるんでおく。ただし、Disposeが呼ばれてもインスタンス
 (つかメモリ領域)はGCまで居座ってる。 

--- : ------ : ------ : ------ : ------ : ---
FUKUDA, (episteme) Fumiki
magical, but never a magic....

[csharpll:0317] Re: <教> リソース開放のタイミング

[ | / | ]
Subject:
[csharpll:0317] Re: <教> リソース開放のタイミング
From:
S.Ono <shuji_ono@...>
Date:
Mon, 20 Mar 2006 15:58:23 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2900.2527
Message-Id:
<020001c64beb$ae7a3480$020ba8c0@magick>
References:
314
小野@どっとねっとふぁん です。

----- Original Message -----
From: "FUKUDA, Fumiki" <fukuda.fm@...>
Subject: [csharpll:0314] <教> リソース開放のタイミング


> すんません、基本的なこと確認させてくださいませ。
> C#では(.NETならなんでもいいけど)、メモリの開放はガベコレ時に
> 行われますけど、メモリ以外のリソースは何時開放されるんでしょか?

実際には実装依存、、、だっけかな?

> こんなとき、ファイルがクローズされるのは何時なんでしょか?
> デストラクタ内で後始末(Close)してるなら、
> ガベコレ直前にデストラクタが動いて…ことになるんすか?
>
> 裏を返せばガベコレなんて何時動くかわかったもんじゃないから、
> 確実にClose()したいなら明示的にClose()を呼べ。ってことでしょか。
>
> あるいはデストラクタ内でCloseしてるんなら、using(...)で囲んで
> おけばスコープ外れるときにDisposeされ、そこでデストラクタが呼ばれて
> めでたくCloseなのかな?

お作法としては、Disposeにリソースを開放する処理を書いて
おきましょう、だったと思います。
で、usingで囲んだときは、スコープを外れるとDisposeが呼ばれるので
そこでリソースの開放が行われるようになる、と。
それと、GCがメモリを回収する際、Disposeが存在しているものに
ついてはまずDisposeを呼ぶという実装がなされているので、GCで
回収されるときもリソースの回収はおこなわれるはず。

#ただし、このとき一回めのGCではDisposeが呼ばれるだけなので
 インスタンス自体は残っちゃうんだったよーな。

このあたりについては「プログラミング Microsoft .NET Framework」に
詳しく書いてあったと思います。

Closeに関しては特にこの手のお作法がなかったよーな。
まぁ、普通Closeなんてメソッドつくればそこでリソースの開放は
するんでしょうけど。

> いや、Javaのときも感じたんだけど、
> 「ガベコレあるから散らかしっぱなしにできて楽ちん」
> ってのは"うそっぱち"ですよね? 少なくともメモリ以外のリソース
> を使ったんならプログラマが責任もってお片づけしたらんと。

Disposeのお作法どおりにつくられてるならGC時点での回収は
保障されるので、気にしなくても一応は動くはず、というレベルですね。
Disposeが実装されてるものはなんでもかんでもusing使え、というのが
あったよーな。。。

----------------------------------------
  小野@どっとねっとふぁん でした。
   http://dotnetfan.org/
----------------------------------------

[csharpll:0319] Re: <教> リソース開放のタイミング

[ | / | ]
Subject:
[csharpll:0319] Re: <教> リソース開放のタイミング
From:
FUKUDA, Fumiki <fukuda.fm@...>
Date:
Mon, 20 Mar 2006 16:07:07 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1506
Message-Id:
<085201c64bec$f18afa60$e5d2060a‐at‐stf.ncos.nec.co.jp>
References:
314 317
επιστημηです。

> Disposeのお作法どおりにつくられてるならGC時点での回収は
> 保障されるので、気にしなくても一応は動くはず、というレベルですね。
> Disposeが実装されてるものはなんでもかんでもusing使え、というのが
> あったよーな。。。

なんだかなー…
なんもかんもusingでくるめって薦めるくらいなら、
言語仕様でautomatic変数許せばいいじゃん。ねぇ?
# 「それってC++/CLI?」 「…そーとも言う」

[csharpll:0321] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0321] Re: <教> リソース解放のタイミング
From:
Imabeppu <imabeppu@...>
Date:
Mon, 20 Mar 2006 16:24:16 +0900
X-Mailer:
Becky! ver. 2.24.02 [ja]
Message-Id:
<20060320161516.8487.IMABEPPU‐at‐jp.fujitsu.com>
In-Reply-To:
319
References:
317 319
Imabeppu です。

Quoted from
Subject: [csharpll:0319] Re: <教> リソース開放のタイミング
From: "FUKUDA, Fumiki" <fukuda.fm@...>
Date: 2006/03/20 16:07:07 (Mon, 20 Mar 2006 16:07:07 +0900)

> なんもかんもusingでくるめって薦めるくらいなら、
> 言語仕様でautomatic変数許せばいいじゃん。ねぇ?

 automatic 変数を許すとして、どんな書き方になるんでしょうね。
 特別な書き方をするなら、using 書くのと大差なくなってしまいそう
 です。

 C++ のデストラクタのよいところの一つとして、何かし忘れてもデス
 トラクタがやってくれて安心、安全というのがあると思います。とな
 ると、ふつーの書き方で自動で Dispose が呼ばれるようなルールが
 欲しいです。

 たとえば、あるスコープ内で new して、そのスコープを抜けるとき
 にそのオブジェクトを誰も参照していなければ、自動で Dispose を
 呼び出してくれるとか。

 うーん、違う問題が出てくるとかなぁ。


--
|=====  ∧ ∧  =====  Imabeppu  =========================|
|==  n(=⌒o⌒=)n  ==  http://homepage3.nifty.com/bep/  ==|

[csharpll:0322] Re: <教> リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0322] Re: <教> リソース解放のタイミング
From:
FUKUDA, Fumiki <fukuda.fm@...>
Date:
Mon, 20 Mar 2006 16:31:51 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1506
Message-Id:
<088e01c64bf0$5b153ab0$e5d2060a‐at‐stf.ncos.nec.co.jp>
References:
317 319 321
επιστημηです。

>   automatic 変数を許すとして、どんな書き方になるんでしょうね。
>   特別な書き方をするなら、using 書くのと大差なくなってしまいそう
>   です。

んむ。
C++/CLIだと:
 Sister^ one = gcnew Sister("恭子"); // GC-heap
 Sister  two("美香"); // auto(stack)
なんすけどね。

>   たとえば、あるスコープ内で new して、そのスコープを抜けるとき
>   にそのオブジェクトを誰も参照していなければ、自動で Dispose を
>   呼び出してくれるとか。

「そのオブジェクトを誰も参照していない」
ことの確認がえらくコスト高だったり。

[csharpll:0323] Re: < 教 > リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0323] Re: < 教 > リソース解放のタイミング
From:
Takao Ono <takao@...>
Date:
Mon, 20 Mar 2006 16:42:31 +0900
X-Mailer:
mnews [version 1.22PL7] 2003-09/29(Mon)
Message-Id:
<060320164231.M0110084‐at‐flame.hirata.nuee.nagoya-u.ac.jp>
In-Reply-To:
322
小野@名古屋大学 です.

う〜, わけわからん. なんでデストラクタと Dispose の両方があるんだ.

<088e01c64bf0$5b153ab0$e5d2060a@stf.ncos.nec.co.jp>の記事において
fukuda.fm@...さんは書きました。
fukuda.fm> >   たとえば、あるスコープ内で new して、そのスコープを抜けるとき
fukuda.fm> >   にそのオブジェクトを誰も参照していなければ、自動で Dispose を
fukuda.fm> >   呼び出してくれるとか。
fukuda.fm> 「そのオブジェクトを誰も参照していない」
fukuda.fm> ことの確認がえらくコスト高だったり。
参照してくれてる人がいるかどうかの確認なら楽 (っつ〜か参照カウン
タ使えば一瞬) なんだけど, プログラム中から参照できるかどうかを確
認しようとすると....
# GC 走らせるのと同じ.
--
名古屋大学大学院 情報科学研究科 計算機数理科学専攻
小野 孝男 (takao@...)

[csharpll:0324] Re: < 教 > リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0324] Re: < 教 > リソース解放のタイミング
From:
S.Ono <shuji_ono@...>
Date:
Mon, 20 Mar 2006 16:50:57 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2900.2527
Message-Id:
<023001c64bf3$05f9a220$020ba8c0@magick>
References:
323
小野@どっとねっとふぁん です。

----- Original Message -----
From: "Takao Ono" <takao@...>
Subject: [csharpll:0323] Re: < 教 > リソース解放のタイミング


> う〜, わけわからん. なんでデストラクタと Dispose の両方があるんだ.

デストラクタ(というかファイナライザというか)は必ずしも呼び出されることが
保障されてなかったよーな>C#
そういえばDisposeは呼び出しが保障されてるんだろか。
本読み返さないと。。。

----------------------------------------
  小野@どっとねっとふぁん でした。
   http://dotnetfan.org/
----------------------------------------

[csharpll:0325] Re: < 教 > リソース解放のタイミング

[ | / | ]
Subject:
[csharpll:0325] Re: < 教 > リソース解放のタイミング
From:
Takao Ono <takao@...>
Date:
Mon, 20 Mar 2006 17:00:22 +0900
X-Mailer:
mnews [version 1.22PL7] 2003-09/29(Mon)
Message-Id:
<060320170022.M0110700‐at‐flame.hirata.nuee.nagoya-u.ac.jp>
In-Reply-To:
324
小野@名古屋大学 です.

O'Reilly の「プログラミングC#」云わく....

<023001c64bf3$05f9a220$020ba8c0@magick>の記事において
shuji_ono@...さんは書きました。
私> う〜, わけわからん. なんでデストラクタと Dispose の両方があるんだ.
shuji_ono> デストラクタ(というかファイナライザというか)は必ずしも呼び出されることが
shuji_ono> 保障されてなかったよーな>C#
遅くとも GC のタイミングで必ず呼出されることが保証されてます.

shuji_ono> そういえばDisposeは呼び出しが保障されてるんだろか。
shuji_ono> 本読み返さないと。。。
こっちは using を使えば本体の実行が終了した時点で呼出されますが,
using を使わないとアウトじゃないかなぁ.

で, 「Dispose() を用意するということは, そのクラスを使用するコー
ドやプログラマに対して『デストラクタの実行を待たずに, Dispose()
を呼んですぐに後始末をしてください』と宣言する」(p. 86) とあって,
しかも例では Dispose() を呼出したときにはデストラクタで二重に後始
末しないようにまでしてます.

えっと....
「デストラクタが呼出されたかどうか」を GC が判断すればいいような....
# デストラクトする時点と GC で回収される時点を区別する必要って,
# どのくらいあるんだろ.
--
名古屋大学大学院 情報科学研究科 計算機数理科学専攻
小野 孝男 (takao@...)

[csharpll:0326] Re: < 教 > リソース解放のタイミング

[ | / ▼ | ]
Subject:
[csharpll:0326] Re: < 教 > リソース解放のタイミング
From:
Shinichi Aoyagi <aoyagi@...>
Date:
Mon, 20 Mar 2006 17:45:16 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2900.2670
Message-Id:
<3c4001c64bfa$9cbf5590$0201a8c0‐at‐divakk.co.jp>
References:
325
青柳です。

----- Original Message -----
From: "Takao Ono" <takao@...>
Sent: Monday, March 20, 2006 5:00 PM
Subject: [csharpll:0325] Re: < 教 > リソース解放のタイミング

> 私> う〜, わけわからん. なんでデストラクタと Dispose の両方があるんだ.
> shuji_ono> デストラクタ(というかファイナライザというか)は必ずしも呼び出されることが
> shuji_ono> 保障されてなかったよーな>C#
> 遅くとも GC のタイミングで必ず呼出されることが保証されてます.

GC が働く前にプロセスが終了してしまう場合などはファイナライザ
が呼び出されることは保証されていないはずです。

話が混じると激しくややこしくなるんですが(^^; GC によって呼び出
されるのはファイナライザです。
C# では 「C++ でのデストラクタの構文」 を使ってファイナライザを
定義できます。
   class Hoge() {
       public ~Hoge() { ... }    // これはファイナライザ
   }

C++/CLI の 「C++ でのデストラクタの構文」 は Dispose パターン
に従った Dispose メソッドやファイナライザを自動生成してくれるシン
タックスシュガーで、ファイナライザは !Hoge() という新しい構文で
定義します。
   class Hoge() {
       public ~Hoge() { ... }    // これは Dispose

       public !Hoge() { ... }    // これはファイナライザ
   }

--
青柳 臣一 (Shinichi Aoyagi)
 Microsoft MVP for Visual Developer - Visual C#  Oct 2005-Sept 2006
 株式会社ディーバ  DIVA Co.,LTD. (Osaka, Japan)

Navigation

検索

[検索ヘルプ]

Maintener: Tietew <www.tietew.jp>
Powered by Ruby on Rails, Mongrel, PostgreSQL, and Hyper Estraier.
click here