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

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

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

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

Unity

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

Q&A

解決済

2回答

20433閲覧

C# List型テクスチャーのメモリ解放

HiruLow

総合スコア55

C#

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

Unity

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

0グッド

1クリップ

投稿2018/02/12 18:45

List<Texture2D> test = new List<Texture2D>(); void Update() { test.Add(new Texture2D(1000, 1000)); if (test.Count >= 20) { test.RemoveAt(0); System.GC.Collect(); } }

上記のような関数を実行した際、ListからTextureは削除されてはいるのですが、メモリからは解放されません。RemoveAtの箇所で削除されるテクスチャをメモリから解放するにはどうすればいいのでしょうか?

List<Texture2D> test = new List<Texture2D>(); void Update() { Texture2D Tmp=new Texture2D(1000, 1000)); test.Add(Tmp); if (test.Count >= 20) { test.RemoveAt(0); System.GC.Collect(); } Tmp=null; }

とすればメモリ解放は出来るのですが、参照元も消えてしまいListの中味が空っぽになってしまいます。

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

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

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

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

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

guest

回答2

0

ベストアンサー

Unityの仕様かC#の仕様か把握しきれていませんが、
確かに「nullが入っていないTextureはGCの対象にならない」という仕様があります。

一応Resources.UnloadUnusedAssets();を使うと、nullが入っていなくとも、どこからも参照されていなければメモリ解放される……らしいのですが、以前自分で検証した際は怪しげでした。
(古い情報&自己流だったのでちゃんとやれば正しく動作するのではないかと思いますが)

別解としては、test.RemoveAt(0);前の行test[0] = null;と入れると確実にGC対象になりますので、ほっといても次のGCタイミングで解放されます。
(null入れる代わりにDestroy(test[0]);でも多分OK)

参考:動的に生成したTextureとSpriteはしっかり管理しよう! - エイリアンプログラム

投稿2018/02/13 00:59

編集2018/02/13 01:29
sakura_hana

総合スコア11427

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

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

0

Object.Destroy を使ってください。
実際のメモリの解放のタイミングは GC.Collect() を使わず
GC に任せておいてください。
その方が効率的だと思います。

また最後の例ですべて消えるというのは信じられません。何かの間違いだと思います。

投稿2018/02/13 00:41

Zuishin

総合スコア28660

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

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

sakura_hana

2018/02/13 01:05

>最後の例ですべて消えるというのは信じられません。 テクスチャ生成→リストがそのテクスチャへの参照を持つ→参照先のテクスチャにnullが入る(リストの参照先が無くなる)→nullが入ったテクスチャはメモリ解放対象→GCで解放される となるので、「Listの中味が空っぽ」は間違いではないと思います。
Zuishin

2018/02/13 01:14

そうなのですか。.NET Framework では考えられないのですが、Unity を使う時には罠になりそうなので覚えておきます。 どうもありがとうございました。
Bongo

2018/02/13 03:22

後者の例、私は実験していないのですが初めて知りました。 ということは、あるTexture2Dオブジェクトが複数のTexture2D型変数から参照されている状態で、それらTexture2D型変数のうちどれか一つにでもnullを代入してしまうと、他の全ての変数からも自動的に参照不能にされて、そのTexture2DオブジェクトはGC対象になって、やがてオブジェクトが解放されてしまうのでしょうか? だとすると、変数へnullを代入するという行為は、かなり注意を払わないとやっかいなバグの原因になりそうですね...
Zuishin

2018/02/13 03:48

例えば string s = "Hello World!"; string t = s; s = null; この場合に t == null になるということですよね? 一時変数を使って二つの変数を入れ替えたりするようなこともできなくなりますね。 こんなのが C# を名乗っていいんでしょうか? C# の規格は標準化されてるのに。
sakura_hana

2018/02/13 04:49

申し訳ありません。検証し直したところ、 「質問内の2番目のコード」→Tmp=nullしてもtexList[0]はnullにならない 「1つのTexture2Dを複数の変数に入れ、どれか1つを=nullする」→他の変数はnullにならない という結果になりました。(Unity5.6.5f1) 別の参照型(Image?)か何かと誤解していたようです。混乱させて申し訳ありません。 ……そしてこれだと、質問内のコードでメモリ解放されてる理由が確かに不明ですね。 test.RemoveAt(0);のタイミングでGC対象になるなら1つ目のコードでもメモリ解放されそうなものなのに。
Zuishin

2018/02/13 04:55

間違いでしたか。安心しました。 検証ありがとうございます。 しかし他の参照型でも C# の規格に沿っている限り考えにくいですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問