- - PR -
[C#] デリゲートをGCの対象から外す方法
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-01-26 12:54
面白い展開になってましたね。置いてかれてました。
そもそもメソッドのアドレスって GC によって移動しちゃうんでしょうか。デリゲートインスタンスのアドレスは動いたとしても、Jit Compile されたページが動くんでしょうか。 アンマネージワールドに渡しているのは、デリゲートインスタンスのアドレスか?メソッドのアドレスか? 前者だとしたら、GC による回収は防げても移動は避けられないんですよね(多分)。後者だとしたら、デリゲートインスタンスの寿命は関係ないような気がします。
デリゲートインスタンスが生きている間は、メソッドのアドレスが移動しないという意味でしょうか? _________________ 囚人のジレンマな日々 | ||||||||||||||||
|
投稿日時: 2007-01-26 13:21
こんにちは。
分かりきっていることでしょうが… オブジェクト指向プログラミングでは、一般に (オブジェクト = データ + メソッド) という認識がされあるように思われます。 オブジェクトとはデータとメソッドがセットになっていると。 では、スタック領域やヒープ領域のメモリ上にオブジェクトが割り当てられた場合を考えてみます。 実際メモリ上に配置されるのは、オブジェクト(データ + メソッド)ではなく オブジェクトの内のデータ部分だけになるはずです。 (さらにC++の仮想関数テーブルようなデータも含まれるでしょう。) ではメソッド本体はメモリのどの部分に配置されるでしょう。 Intel CPUの場合で考えますと ・JITコンパイルずみのネイティブコードは、 CS:コードセグメント(セレクタが示すGDT/LDTで示される)領域にあるはずです。 ・スタック領域に配置されたデータは SS:スタックセグメントの領域にあるでしょう。 ・ヒープ領域に配置されたデータは、おそらく DS:データセグメントで示される場所にあると思います。 …という風に、 オブジェクトといってもデータとメソッドはメモリ上の別々の領域にあるはずです。 ガルベージ・コレクタの対象となるのは、データ領域だけですよね。 なので、コード領域にあるメソッドのアドレスが移動することはないのだと思います。
よく分からないですが、私の予想では クラス・アセンブリ・AppDomainがアンロードされるまでは有効な気がします。 | ||||||||||||||||
|
投稿日時: 2007-01-26 13:53
前に挙げた、 http://msdn.microsoft.com/msdnmag/issues/06/05/bugbash/default.aspx#S3 を見ると、デリゲートがGCで回数されるまで、と思われます。 っていうかそれはつまり普通にMSDNとかで書いてあるような話と同じ、ですけど。 | ||||||||||||||||
|
投稿日時: 2007-01-26 14:01
それは「コードセクションに x86 のコードがある」だけで「有効」と呼べる状態ではないんじゃないですかねぇ。 | ||||||||||||||||
|
投稿日時: 2007-01-26 14:06
すべてのセグメントが、単一の広大なメモリ空間を指し示すような実装がありふれていることを考えれば、スタックもコードも移動しない保証はない気が。 | ||||||||||||||||
|
投稿日時: 2007-01-26 14:38
こんにちは。
うーん、内容が難しくて意味が良く分からなかったですが、 確かに「アンマネージコードの関数ポインタが無効になる」と書いてありますね。 ”サンク”が具体的にどんなものか、少し調査してみようと思います。
そうなんですか? GDT,LDT,IDTなどのディスクリプタテーブルで領域サイズを覗かれたのですか?
スレッドごとにスタック領域を持っているのは分かりますが、 1プロセスの開始から終了までの間に、 スタックやコードの領域が移動することってあるのでしょうか? | ||||||||||||||||
|
投稿日時: 2007-01-26 14:49
マネージな世界に関してスタックは微妙かな?と思うところ(*1)がありますが、メモリにロードされたアセンブリのイメージやJITによって生成されたコードが移動されることは、.NET の今のバージョンでは無さそうに思いますねぇ。 *1 マネージスレッドはOSのスレッドそのものではないし、yield なんかの存在を見ると、スタックに関しては「移動」するかどうかはともかく、積極的に管理する(したい)方向なのかな、と。 | ||||||||||||||||
|
投稿日時: 2007-01-26 15:32
こんにちは。
マネージスレッドは、OSスレッドとは違うんですね!? ドキュメントを見てもイマイチ理解できないです。 やっぱりソースを見てみないと正体が分かった気になりません。 # Java(sum JVM)では、JavaThreadがOSスレッド(Windows:CreateThread, Solaris/Linux:pthread)で分かりやすいのになぁ。 yieldとはなんでしょうか?(yield returnのこと??) もうすこし詳しく教えていただけるとうれしいです。 #あれ!?本題とかけ離れてきた気が… |