質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

1回答

2395閲覧

クラスのフィールドのメモリ解放タイミング

osaka-umeda

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2020/08/09 16:48

クラスのフィールド(メンバー変数)の挙動に関する質問となります。

あるAというクラスがあり、
AのフィールドにはBという構造体(フィールド名BB)、Cというクラス(フィールド名CC)があります。

Aのクラスをnewして使っており(newしたインスタンスへの参照を変数AAに入れているとします)
使い終わったので、変数AAにnullを代入し、確保したインスタンスを解放(厳密にはGCのコレクション対象にする)した場合、
AのフィールドであるフィールドBBはAAが実際にGCにコレクションされた際に解放され、
フィールドCCは、GCにコレクションされた際にはCCにnullをセットしていないので解放されないのでしょうか?

それとも参照型のフィールドに関しては、nullをセットしなくても自動的にnullがセットされた状態?になるか、
または強制的に解放されるような仕組みでしょうか?

自分でファイナライザで参照型のフィールドにはnullをセットしなければいけないのかが
ネットで検索しても上手くヒットしなかった為、質問させて頂きました。
宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/08/09 22:24

Dispose パターンというのをご存じですか? それを実装しなければならないのはどういうケースかご存じですか? そのあたりが分かっていればこのスレッドの質問はしなくてすんだと思います。
hihijiji

2020/08/10 02:27

そもそもnullをセットすること自体が蛇足です。
退会済みユーザー

退会済みユーザー

2020/08/10 02:48

>フィールドCCは、GCにコレクションされた際にはCCにnullをセットしていないので解放されないのでしょうか? マイクロソフトの資料だと、gentaroさんのリンクの詳細にあたる https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/fundamentals#fundamentals-of-memory この辺が相当しています。 以下、上記資料とガーベッジコレクションという言葉からの類推ですが、GCの基本はマークアンドスイープだと思うので https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%BB%E3%82%A2%E3%83%B3%E3%83%89%E3%83%BB%E3%82%B9%E3%82%A4%E3%83%BC%E3%83%97 AAがコレクトされたなら、AAから参照されているCC以外に、有効なスレッド/タスクから辿れるCCを参照している人がいなければCCもコレクトされると思います。 そこまでしてる人はなかなかいないと思いますが、ソースとかはこの辺にあるので、厳密に知りたければそちらを辿って読んでください。 https://referencesource.microsoft.com/#mscorlib/system/gc.cs またDisposeはリソースの話なのでメモリとは関係ありません。 リソースの開放はGCにコレクトされた後のファイナライズをのんびり待てるほど余裕がないものも多いので、そのために別途用意された機構がDisposeだと思っています。
Zuishin

2020/08/10 03:03

CC は AA への参照が無くなった時点でルートからたどれなくなるのでガベージコレクション対象になります。null 代入は不要です。AA と CC のどちらが先に解放されるかは決まっていません。BB については構造体なのでガベージコレクションされません。AA のメモリの一部なので AA がコレクトされてメモリが解放されることが BB の解放になります。
退会済みユーザー

退会済みユーザー

2020/08/10 03:04

> またDisposeはリソースの話なのでメモリとは関係ありません。 違いますね。 > リソースの開放はGCにコレクトされた後のファイナライズをのんびり待てるほど余裕がないものも多いので、そのために別途用意された機構がDisposeだと思っています。 これも違います。
osaka-umeda

2020/08/10 06:40

皆さんからのご返信にすごく助かっております。ありがとうございます。 >CC は AA への参照が無くなった時点でルートからたどれなくなるのでガベージコレクション対象になります。null 代入は不要です。 上記はCCをAAから取得し、外部の誰かが参照していた場合も考えられるかと思いますが、その場合はAAにnullをセットしたら、内部挙動としては、AA内のCCにはnullがセットされるような形になり、外部の誰かが参照している変数にnullをセットされるまではCCの実体は解放されないという挙動で合っておりますか? > またDisposeはリソースの話なのでメモリとは関係ありません。 これは、ファイルオープン系とかのネットワーク係のリソースでは自動的にクローズされないので、メモリとは関係ないというような意味で合っておりますか? 宜しくお願いします。
Zuishin

2020/08/10 06:47

> という挙動で合っておりますか? 合っていません。null の代入は忘れてください。hihijiji さんのおっしゃる通り、蛇足でしかありません。 他から参照されているのであればガベージコレクションの対象にはならないので解放もされません。null を代入しようがすまいが同じです。内部で代入されるということもありません。
退会済みユーザー

退会済みユーザー

2020/08/10 06:56

@osaka-umeda > これは、ファイルオープン系とかのネットワーク係のリソースでは自動的にクローズされないので、メモリとは関係ないというような意味で合っておりますか? 合ってますよ。SurferOnWwwさんが言いたいのはアンマネージドリソースだから違うとかアンマネージドなメモリとかが違うとか駄々をこねてるだけだと思います。その証拠に理由を書いてないですからね。 マネージリソースだってアンマネージドリソースを使います。マネージリソースがcloseされずに放置されてたなら、システムやフレームがどう頑張ってもアンマネージドリソースを開放することができない=マネージリソースの開放も目的にしてるのですよ。
osaka-umeda

2020/08/10 07:51

皆さんご返信ありがとうございます。 > 合っていません。null の代入は忘れてください。hihijiji さんのおっしゃる通り、蛇足でしかありません。 > 他から参照されているのであればガベージコレクションの対象にはならないので解放もされません。null を代入しようがすまいが同じです。内部で代入されるということもありません。 C#では、nullを自分でセットするようなことは全般的にしなくて大丈夫ということでしょうか? メソッド内のローカル変数じゃない場合は、明示的に使わなくなったフィールドに関してはnullをセットしてあげないといつまでも保持してしまうので、必要なくなったフィールド(参照型)にはnullをセットして使っていないようにしないといけない(参照カウンターをゼロにする)と思いますが、 フィールドじゃなく、そのフィールドを保持しているクラスの変数自体は、そのクラスの変数にnullをセットしてあげれば、 内部のフィールドに関しては、特にnullをセットしなくてよいという意味で合っておりますか? > マネージリソースだってアンマネージドリソースを使います。マネージリソースがcloseされずに放置されてたなら、システムやフレームがどう頑張ってもアンマネージドリソースを開放することができない=マネージリソースの開放も目的にしてるのですよ。 なるほど、理解出来ました。ありがとうございます。
Zuishin

2020/08/10 08:05

参照カウンターは使われていません。もっと賢い方法で判定しています。リンクされたページを詳しく読んでみると書いてあるんじゃないでしょうか。
退会済みユーザー

退会済みユーザー

2020/08/10 08:06

> C#では、nullを自分でセットするようなことは全般的にしなくて大丈夫ということでしょうか? 個人的な感覚で言えば大丈夫です。 nullにしてあげればGCがマークアンドスイープする際にトラバースする区間が減って楽をするケースはあるかもしれません。時代的にはnullを使用しない流行りのようなものもありますし、親切心からnullにして、NullPointerExceptionが起きてお前のせいだ~となるケースだってあるかもですね。 基本nullを使う設計なら、個人的にお作法として使用しないときはnullが良いとは思います。
退会済みユーザー

退会済みユーザー

2020/08/10 08:13

> マネージリソースだってアンマネージドリソースを使います。マネージリソースがcloseされずに放置されてたなら、システムやフレームがどう頑張ってもアンマネージドリソースを開放することができない=マネージリソースの開放も目的にしてるのですよ。 そういうの初耳。先のスレッドで Microsoft の公式文書の裏付けがないとレスは意味がないというようなことを言っていましたよね? どの文書のどこにそういうことが書いてあるか教えてくださいな。
退会済みユーザー

退会済みユーザー

2020/08/10 08:40 編集

質問者さん> .NET アプリでリソースの開放には Dispose パターンを実装します。ただし、 アンマネージドリソース ⇒ GC で解放できない ⇒ Dispose パターン利用・・・ということです。 裏を返せば、アンマネージドリソースを使ってなければ Dispose パターンの実装は不要 ⇒ 今回の質問のマネージドリソースは GC 任せでよい(null をセットとかは必要ない)ということです。 ということで、最初の私のコメント、 > Dispose パターンというのをご存じですか? それを実装しなければならないのはどういうケースかご存じですか? ・・・に対する答えが Yes であれば、今回の質問は出てこないはず。 なお、Dispose パターンの実装はアンマネージドリソースで使用されるメモリを解放する目的もあるわけで、メモリに関係ないということではありません。
退会済みユーザー

退会済みユーザー

2020/08/10 08:47

> 基本nullを使う設計なら、個人的にお作法として使用しないときはnullが良いとは思います。 あなたが重視している Microsoft の公式文書の裏付けはあるのでしょうか? あなたが言うには Microsoft の公式文書の裏付けがないと意味がなく、個人的に「良いとは思う」なんてのは問題外だったのでは?
osaka-umeda

2020/08/10 12:49

色々とご説明、みなさんありがとうございます。 アドバイス頂いたMSのガベージコレクションの説明ページを読んでいて、1点気になったのが、nullをセットしないで問題ないと皆さんからのご返信がありましたが、もし、シングルトンパターンで、マネージャーのようなクラスが常に存在しており、処理するオブジェクトを管理していた場合は(このオブジェクト群はこのマネージャーしか参照していない)、そのオブジェクトをGCの対象にする為にもnullがセットされていないといつまでも参照されているので解放されないと思うのですが(勝手にGCされてしまったら、マネージャーがもしどこかのタイミングでそのオブジェクトを実行しようとした時に勝手に解放されていたら困るので)、この認識は間違いでしょうか?
Zuishin

2020/08/10 12:52

シングルトンはアプリの終了まで生き続けるオブジェクトなので、終了処理は考えなくて大丈夫です。
osaka-umeda

2020/08/10 13:04

すみません、シングルトンのクラスが各オブジェクトを管理しているような場合となります。 例えばですが、UIパーツ(ボタン等)を管理するようなUIマネージャーがあった場合に各UIパーツをUIマネージャーに登録して管理してもらっているのですが、UIとして必要なくなったパーツ(オブジェクト)に関しては、UIマネージャーが管理してるオブジェクトの配列にnullをセットして、そのUIオブジェクトがもう使われていない形にするという意味となります。
Zuishin

2020/08/10 13:11

シングルトンの悪い使い方ですが、それはともかく、寿命の短いオブジェクトを破棄するのであれば null を代入するのが手っ取り早いと思いますが、使い終わったとしても別に放っておいて大丈夫です。スマホのようなメモリの小さな機器で巨大なメモリを使うなら話は別ですが、普通それが問題になることはないと思います。どうせ GC などめったに働かないので。
osaka-umeda

2020/08/10 13:24 編集

すみません、少し話がそれてしまうのですが、シングルトンの悪い使い方というのが理解できずでして、変な意味では無いのですがUIマネージャーのようなのがシングルトンの場合は、管理しているUIに関して全てを非アクティブに出来たり、管理しているUIの中から何かを探す等、すごく便利でして、またUIのマネージャーが複数存在しても困るのでシングルトンなのですが、悪い使い方となりますか?逆に良い使い方というのが思いつかなかったので確認させていただきました。 その為、メモリも使いっぱなしではなく、使用していないオブジェクト(今回であればUIパーツ)に関してはnullをセットして使っていない形にするのは特に問題もなく、UIマネージャー的にも管理しなくてよくなるパーツになるのと、GCの対象にもなるので、nullセットは良い形かと考えていますが、すごく悪い方法なのかとおもってきてしまいました。
Zuishin

2020/08/10 13:29

データバインディングを使えば UI を探さなくて済むのでマネージャーは不要です。また、寿命の短い UI をシングルトンという寿命の長いオブジェクトで管理する意味もありません。どうしても探さなければならない時には親から探せばいいだけです。
osaka-umeda

2020/08/10 13:35

データバインディングのほうをネットで調べてみますね。
退会済みユーザー

退会済みユーザー

2020/08/10 13:41

@SurferOnWww あなたが書かなかった理由を推測して書いただけですよ。あなたの書いた理由でいいのなら、マネージリソースというのを考慮しないでいいので、リソースの開放に使うのがDisposeで今回の件には無関係で終わりです。裏を返す必要などないのですよ。私が別の質問で書いたのは、WCFの使い方を説明するのに、MSのリンクも提示せずに自分のHP紹介だけするのは何事か?という話で、それも今回の件とは無関係です。 @osaka-umeda 話が混迷を極めてますが、シングルトンで静的に確保というのは悪手ではありませんよ。 ただ性格がグローバル変数と同じなので、忌み嫌われる傾向にあります。 プロセスに対して1つであることが役割上望まれているオブジェクトはシングルトンで問題ありません。 ただZuishinさんのおっしゃるとおり.NETでは基本UIはバインディングで構築するのが普通ですね。モデルがメインになり、UIはそれを透過的にに反映させるだけというのが理想形だと思います。UIマネージャが何をするものか分かりませんが、相反するものであれば、あまり一般には好まれないものかもしれません。
Zuishin

2020/08/10 13:47 編集

> プロセスに対して1つであることが役割上望まれているオブジェクトはシングルトンで問題ありません。 シングルトン自体に罪はありませんが、今回の目的には適しません。「悪い使い方」と書いたのは、 - 寿命の短い UI をシングルトンの中で取り換えながら使っている - コントロールをフォームやウィンドウから外に出し、グローバルに使えるようにしている が、主な理由です。
osaka-umeda

2020/08/10 13:52

皆さま、諸々ありがとうございます。 これより先は自分で調べて、悩んだ際には再度質問させて頂ければと思います。 本当に助かりました、ありがとうございます。
退会済みユーザー

退会済みユーザー

2020/08/11 00:57 編集

> あなたが書かなかった理由を推測して書いただけですよ。あなたの書いた理由でいいのなら、マネージリソースというのを考慮しないでいいので、リソースの開放に使うのがDisposeで今回の件には無関係で終わりです。裏を返す必要などないのですよ。 意味不明。少なくとも 2020/08/10 17:13 と 2020/08/10 17:47 の私の質問の答えがない。自分でも何を書いているのか分かってないとか?
退会済みユーザー

退会済みユーザー

2020/08/11 00:46 編集

> 私が別の質問で書いたのは、WCFの使い方を説明するのに、MSのリンクも提示せずに自分のHP紹介だけするのは何事か? WCFの使い方を説明? 誰が? そもそもレスのリンク先は読んでないと言ってた気がするけど?
退会済みユーザー

退会済みユーザー

2020/08/11 01:00 編集

もう一度聞きますが、逃げないで先の私の質問(以下に再掲)に答えてもらえませんか? あなたのレスを質問者さんが信じてしまってますけど。特に「マネージリソースだってアンマネージドリソースを使います」というところは決定的に間違っていて、そこをベースに始まるその後の記述も間違っているのでは? > マネージリソースだってアンマネージドリソースを使います。マネージリソースがcloseされずに放置されてたなら、システムやフレームがどう頑張ってもアンマネージドリソースを開放することができない=マネージリソースの開放も目的にしてるのですよ。 そういうの初耳。先のスレッドで Microsoft の公式文書の裏付けがないとレスは意味がないというようなことを言っていましたよね? どの文書のどこにそういうことが書いてあるか教えてくださいな。
guest

回答1

0

自分でファイナライザで参照型のフィールドにはnullをセットしなければいけないのか

マネージドリソースの話だと仮定しますが、そもそもそんな事を意識する必要がないのがガベージコレクション利点です。

ざっくり言えば、アプリケーションからどのように参照されているのかはGC側が把握しており、階層構造がある場合でもトップレベルのオブジェクトへの参照がなくなっているのであれば、芋づる式で開放されます。

ネットで検索しても上手くヒットしなかった為、質問させて頂きました。

GCについて詳しく知りたいのであれば、公式リファレンスに載ってます。

ガベージ コレクション

投稿2020/08/09 19:14

gentaro

総合スコア8947

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問