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

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

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

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

4704閲覧

staticクラス、メソッド内でnewした場合GCされるのか

tc97

総合スコア14

C#

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2021/04/13 05:07

編集2021/04/13 05:08

質問内容

題名の通りですが、
staticメソッド内でnewした場合も、参照されなくなった時点でGCが走るのでしょうか?
例えば、何らかの値をうけとってMatrix4x4を返すstaticメソッドを考えたとき、

C#

1public static Matrix4x4 Method1(int val) 2{ 3 var mat = Matrix4x4.identity; 4 mat.setRow(0, new Vector4(val, val+1, val+2, val+3)); 5 mat.setRow(1, new Vector4(val, val+1, val+2, val+3)); 6 mat.setRow(2, new Vector4(val, val+1, val+2, val+3)); 7 mat.setRow(3, new Vector4(val, val+1, val+2, val+3)); 8 return mat; 9} 10

このnewしたVectorはmatが参照されなくなってGCが走ると破棄される、で理解はあっていますでしょうか?

背景

UnityでNative Pluginとの連携を考えているのですが、コールバック関数として渡すためにはstaticでないといけないようなので、staticメソッドを定義

staticメソッド内でどこまで処理をしてよいのかよく分かっていない

という流れで本質問に至っています。

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

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

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

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

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

guest

回答2

0

ベストアンサー

いろいろ勘違いがあったようですm(_ _)m

Matrix4x4Vector4は、値型であるためスタックメモリの上に作られます。
matMatrix4x4型のため、スタックメモリに確保され、=によって直接値が代入されます。
その後の操作を経て、return mat;に到達したとき、
呼び出し元へと値を返すために、matの値のコピーが作られます。
そして、メソッドの終了と共に、スタックメモリ上にあるmatの情報は解放されます。
スタックメモリ上にあるデータは、GCの管理外なので、GCは関わってきません。

呼び出し元には、さっき作ったコピーの値が渡されます。
呼び出し元が変数を用意してそれを受け取っていた場合、その値がその変数へと格納されて、
コピー自体は役目を終えて消えます。

このnewしたVectorはmatが参照されなくなってGCが走ると破棄される、で理解はあっていますでしょうか?

なので、参照とは関係なく、この時newしたVectorそのものは、メソッドの終了と共に破棄されます。
しかし、returnを通じて、その値のコピーは呼び出し元に渡される。といった感じになるかと思います。


ついでに、ではもしnewされたものが、参照型のものであったなら、ですが、
この場合は、GCの対象になるのは、そのインスタンスへの参照が1つもなくなった時です。
GCは全ての参照変数の参照先をチェックして、それを元に各インスタンスに参照されているかどうかのマークを付けます。
その結果、マークされていない=どの変数からも参照されていないインスタンスはGCの対象となります。

このコードでいえば、matに参照が代入された時点で、インスタンスは参照されている状態です。
確かに、このまま何もせずに、matが無効になれば、どこからも参照が無くなり、GCの対象となります。
しかし、このコードでは、return mat;として、メソッドの外にインスタンスへ参照を返しています。
当然、このメソッドを呼び出した側では、それを受け取っていると思います。(絶対ではないですが)
この外部の参照がある限り、たとえメソッドの終了により、matが破棄されても、
作られたインスタンスの参照は無くなりません。
その為、メソッドの終了後もその参照がある限りインスタンスはGCの対象にはならず、生き続けます。
(もしメソッドを呼び出した側が返り値を受け取っていなければ、メソッドの終了時点でGC対象になります)

作られた場所がstaticメソッドであるかどうかは、あまり関係がありません。
(staticメソッドであっても、ローカル変数は呼ばれるたびに作られ終了と共に解放されます)


このnewしたVectorはmatが参照されなくなってGCが走ると破棄される、で理解はあっていますでしょうか?

GCの対象になるのは、そのインスタンスへの参照が一つもなくなった時です。
このコードでいえば、matに参照が代入された時点で、インスタンスへの参照は1となります。
確かに、このまま何もせずに、matが無効になれば、被参照数も0となり、GCの対象となります。
しかし、このコードでは、return mat;として、メソッドの外にインスタンスを返しています。
当然、このメソッドを呼び出した側では、それを受け取っていると思います。(絶対ではないですが)
この外部の参照がある限り、たとえメソッドの終了により、matが破棄されても、
作られたインスタンスの被参照数は0にはなりません。
その為、メソッドの終了後もその参照がある限りインスタンスはGCの対象にはならず、生き続けます。
(もしメソッドを呼び出した側が返り値を受け取っていなければ、メソッドの終了時点でGC対象になります)

作られた場所がstaticメソッドであるかどうかは、あまり関係がありません。
(staticメソッドであっても、ローカル変数は呼ばれるたびに作られ終了と共に解放されます)

投稿2021/04/13 09:28

編集2021/04/14 00:49
amiya

総合スコア1218

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

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

Bongo

2021/04/13 12:12

丁寧なご説明だと思います。気になる点を挙げさせていただきますと、ご回答を拝見しますに参照カウント方式のご説明のように見受けられますが、Unityの場合は「自動メモリ管理 - Unity マニュアル」(https://docs.unity3d.com/ja/current/Manual/UnderstandingAutomaticMemoryManagement.html )を見ますにマーク&スイープ方式をベースにしたご説明の方がふさわしいかもしれない...ということと、UnityのVector4(https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector4.cs )やMatrix4x4(https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Matrix4x4.cs )は値型ですので、挙動が違ってくるんじゃないかな...ということでしょうかね。
amiya

2021/04/14 00:31

いろいろ勘違いがあったようです。ありがとうございます。
tc97

2021/04/14 01:33

amiya様、Bongo様ともご丁寧な回答ありがとうございます。 大変参考になりました。 自分もMatrix4x4型やVector4型のことを勘違いしていて、参照型のつもりで質問していました。 - 値型の場合はスタックに積まれるため(値渡しするため)問題なし - 参照型の場合は(staticか否かは関係なく)参照が残る限りGCの対象にはならない。返り値を返している場合、その返り値をうけとっているインスタンスが生存する限りは(参照がなくならない限りは)、GCの対象にならない と、理解しました。
guest

0

どこでnewしようが、参照が完全に無くなればそのうちGCが回収します。
適当なクラス書いて、デストラクタの動作を見れば自分ですぐ確認出来ると思いますが。

投稿2021/04/13 05:30

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tc97

2021/04/14 01:33

ありがとうございます。 確認してから質問すべきでしたね、すみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問