• ベストアンサー

C#のガベージコレクタについて

お世話になります。 現在C#で画像関連のプログラミングをしています。 ガベージコレクタがあるため安心してプログラムを組んでいたのですが、 参照されない画像を開放しないでいると、タスクマネージャーからメモリがどんどん増えていくのが確認できました。 具体的には、PictureBoxのImageに繰り返し代入していました。 ガベージコレクタは参照されなくなった変数を取りあえず放っておいて、 メモリが一杯になってきたら開放処理をするため、 快適なソフトを作るためにはできるだけガベージコレクタに頼らない方が 良いと考えました。 ですので今プログラム全体を見直して開放処理を加えているのですが、 厳密に言うとstring等にも開放処理を加えたほうがいいのでしょうか? newで確保した変数や、関数からオブジェクトを受け取った時などは全て開放しなければ いけないと思いますが、この認識で合っているでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • DeForest
  • ベストアンサー率44% (4/9)
回答No.1

基本的にはガベージコレクタに任せていて大丈夫です。 画像でどんどん空きメモリが減っていくのが気になるのであれば、pictureBox1.Image = Image.FromFile(xxx); のように PictureBox に直接 Image オプジェクトを設定する書き方になっていたら、Imageクラスのオブジェクトは一旦オブジェクト変数に置いて、完全に不要になった時点で image1.Dispose() として明示的に解放するように書きなおせばよいと思います。 ガベージがどうしても気になるなら、適切な位置で System.GC.Collect() を実行すれば良いでしょう。

masaota56
質問者

お礼

ありがとうございます。 とりあえず if (pictureBox1.Image != null)   pictureBox1.Image.Dispose(); pictureBox1.Image = Image.FromFile(filenName); のようにして対処しました。 また、色々試すうちに気づいたのですが、Formに乗せたImageListは Formを閉じてもなかなか開放されないようで、FormのDisposeをオーバーライドして imageList1.Images.Clear(); imageList1.Dispose(); を入れるとおおむね直ぐに開放してくれるようでした。 とりあえず画像はちゃんと開放するようにしてみます。

その他の回答 (2)

  • taku2888
  • ベストアンサー率60% (15/25)
回答No.3
masaota56
質問者

お礼

ありがとうございます。参考にさせていただきます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

C# のガベージコレクションがどうなっているかは知りませんが, 多くのガベージコレクションでは「OS から見たときのメモリ使用量は減らない」んじゃないですかね. 「OS に返す」のではなく, 「次にメモリを使うときのためにとっておく」のが普通だと思います. まあ, いずれにしてもガベージコレクタを適切なタイミングで実行するのはよいことだと思います. その方がレスポンスも読めるし. 実際, 組み込み系などリアルタイム処理を要求されるところでは, 「ガベージコレクションをシステムに任せるとよくわからんタイミングで起きてその処理にかかる時間も要求された仕様を満たせるかどうかわからない」という理由でガベージコレクションを使わないということもあるようです.

masaota56
質問者

お礼

No.1さんへのお礼のように対処しましたところ、タスクマネージャで確認する限りは メモリの使用量が減ったようです。対処方法がガベージコレクションに関係していたか どうかは分かりませんが、とりあえずOSに返してくれたようでした。

関連するQ&A

  • [言語C#] string型における参照値の受け渡し

    stringは、参照型に分類されると思います。・・・(1) 【string宣言部抜粋】 public sealed class String : IComparable, ICloneable...... また、参照変数の代入では、オブジェクトの参照値が受け渡されるという認識です。・・・(2) 上記(1)、(2)を踏まえると、次のプログラムの実行結果に納得がいきません。 string aiu = "aiu"; string aiue = aiu; Console.WriteLine(aiue); aiu = "abc"; Console.WriteLine(aiu); Console.WriteLine(aiue); 出力結果---------- aiu abc aiu ------------------ (1)、(2)の考えを取り入れた場合、出力結果は aiu abc abc になるものだと思いましたが、なぜこのような結果になるのでしょうか 。自作クラスで似たような処理を行った場合では、一方の変更が同じインスタンスを代入した他方へも影響することは確認済みです。 ただ、stringの場合では・・・違うみたいです。 初歩的なことだと思いますが、宜しくお願い致します。

  • Stringオブジェクトについて

    ある参考書では、Java のメモリー使用効率を改善するために、JVM は「String 定数プール」と呼ばれる特別なメモリー領域を確保していると書いてあり、String を作成する例として次の2つのパターンのコードについて説明している(この例では、定数プール内にほかのString は存在しないものとしている)。 ・パターン(1) String s = "abc"; // 1つのString オブジェクトと         // 1つの参照変数を作成する この例では、"abc" がプールに納められ、変数s がそれを参照する。 ・パターン(2) String s = new String("abc"); // 2つのString オブジェクトと                  // 1つの参照変数を作成する。 このコードでは、new キーワードを使ったので、新しいString オブジェクトが標準の(プールでない)メモリー上に作成され、変数s がそれを参照する。さらに、リテラル"abc" がプールに収められる。  そこで質問ですが、パターン(2) で、変数s と2つのオブジェクトはそれぞれ互いにどのような関係(メモリー上の関係も含めて)を持っているのか。 例えば変数s に対してプリント命令を出したときにJVM はこの2つのオブジェクトに対してどのような処理をするのか。 またこれらのオブジェクトのhashcode はどうなっているのでしょうか。どなたか教えてください。

  • Javaのプログラミングにおいて、暗黙的にオブジェクトが生成される場合はどんな場合ですか?

    Javaアソシエイツの資格取得ため、勉強しています。詳しい解説を求めています。 ■問題 次のプログラムを実行すると、出力結果はどのようになりますか。1つ選択してください。 http://d.hatena.ne.jp/motoi20/20081210 ■解説 正解は選択肢Aです。func(s)では、変数sが参照しているStringオブジェクトを「func(Stirng s)」の引数sに渡しています。func()メソッドの処理で「s+"Hello"」という処理をしたとき、内部では暗黙的に新しいStringオブジェクトが生成されます(変数sに文字列を追加しているわけではありません。)func()メソッドの呼び出しが「s=func(s)」となっていた場合、main()メソッド内の変数sが新しくできたオブジェクトを参照するため、結果の出力は「JavaHello」になりますが、「func(s)」の呼び出しでは戻り値を再代入していないため、変数sは文字列「Java」を保持したオブジェクトを参照します。Stringクラスは読み取り専用オブジェクトであることに注意しましょう。 ■疑問 通常、オブジェクトを作成するのは、「new」を使って行うわけですよね?暗黙的にオブジェクトが生成されるのは、どういう場合でしょうか?読み取り専用オブジェクトだから何に気をつければいいのでしょうか?

  • C++のnewで確保したメモリーの解放の確認方法

    C++で作成中のプログラムの一部で、長い文章も処理できるように、構造体とメモリーの動的確保を使用しています。 ただ、動的に確保したメモリーは自分で解放しなくてはならないのですが、プログラムが単純なうちは開放のミスを発見できますが、長くなるとバグで一部開放されない可能性も捨てきれません。 そのようなときに全て開放できたか確認する方法は無いのでしょうか? 開発環境につきましては、 OS WindowsXP HomeEdition コンパイラ BCC 言語 C++ コンソールアプリケーション struct string { char str[512]; struct string* nextstr;}; 簡単には、このような構造体を new で確保し、開放は、先頭から delete してますが、 構造体がこれより結構複雑なため、処理部が長くきちんと開放できているか自信が有りません。

  • rubyにおける変数と代入のメモリの様子について

    Rubyの変数と代入演算は、メモリについてどのような扱いになっているのでしょうか。2点ほど疑問電があります。 1点目:代入演算は変数にアドレスを渡しているのか RubyLifeのRuby入門のサンプルをみて学習していたところ疑問がわきました。 http://www.rubylife.jp/ini/var/index4.html を参照しながら示します。 str1 = "Tokyo" str2 = str1 str1 << ",Japan" とやるとstr1もstr2も"Tokyo,Japan"となることから、rubyでの代入演算はアドレスを代入してると考えました。 2点目:新しくオブジェクトを代入すると別メモリ領域において、そのアドレスを代入しているのか str1 = "Tokyo" str2 = str1 str1 = "Osaka" とやると、str1は"Osaka"、str2は"Tokyo"となります。 前述の参照渡と考えるとstr2も"Osaka"となっているはずですが違いました。 ここで解説に(引用はじめ) なお2つの変数が同じオブジェクトを指し示した後で、どちらかのオブジェクトに新しいオブジェクトを 代入した場合は、代入された変数が指し示すオブジェクトだけが変更されるだけです。(引用おわり) とあります。 このことをふまえると、新しいオブジェクトを変数に代入するというのは、別のメモリ領域をつくってデータを置いてから、そのアドレスを変数に代入している、と考えました。 これら2つの考えと実際の仕組みは一致しているのでしょうか、と言うのが質問です。 質問点をまとめると、Rubyにおいて変数に対して ・代入演算はアドレスを代入しているのか(Cでいうポインタの扱いなのか) ・新しいオブジェクトを代入するときには、新メモリ領域を作ってデータを入れてそのアドレスを代入しているのか という点です。 ついこの間はじめたばかりの初心者ですが、どうかご教授よろしくお願いいたします。

    • ベストアンサー
    • Ruby
  • c言語のmalloc関数、またrealloc関数

    c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。

  • C# 画像のトリミング処理

    C#の課題で画像のトリミング処理を行いたいのですが、 どういった処理を行えばいいのか分かりません。 ネットでもいろいろ調べてみたのですが、 Picturebox上に表示させる画像のトリミング方法は見つかっても、 画像そのものにトリミング処理を行う方法は載っていませんでした。 上記のソースを参考にして、 Pictureboxをプリントスクリーンで撮って保存するやり方も試してみたのですが、Pictureboxよりも大きな画像(パソコンの解像度ぎりぎり)の処理で上手くいきません。 C#のソースプログラムでは 画像そのものに直接手を加える形でのトリミング処理は出来ないのでしょうか?

  • C# 変数を変数で指定したい

    UnityとC#でプログラミングの勉強をしている者です。 「操作する変数」を、変数を使って指定するにはどのような方法を使えば良いのでしょうか。 以下、例となります。 aという変数、およびb1、b2、b3……という変数があるとしたとき、 「a=1ならば、b1に1を代入する」 「a=2ならば、b2に1を代入する」 「a=3ならば、b3に1を代入する」…… という処理をする方法を探しています。 よろしくお願い致します。

  • PHPの参照渡しについて

    以下のようなコードがあったとき $obj = new stdClass(); $foo = $obj; この場合、動作は いわゆる【参照の値渡し】というとらえかたでよいのでしょうか? 変数$obj には、 new stdClass();という記述によって 新規に作成されたオブジェクトの参照(※正確には別のメモリ内に保持されたオブジェクトのアドレス) が保持されるわけですよね? そのとき $foo = $obj; というコードは$objが保持するオブジェクトのアドレス値を$fooという変数にも コピーするという動作を意味するわけですよね。 この場合、両変数を用いて生成されたオブジェクトのプロパティなどの状態を 共有することとができます。 しかしながら変数$fooに別の値、例えば文字列を代入すうると $foo = "文字列"; とすると$fooの値が変更され$objの値は変更されません。 対して、次のようなコードがあった場合 $foo = &$obj; というコード、これはPHPにおける参照渡しですが、 この場合は$objが指し示す、オブジェクトが保持されているメモリ上のアドレスではなく そのメモリ上に確保された変数$objそのもののアドレスが$fooという変数にコピー? されるのでしょうか? この明示的な参照渡しだと、オブジェクトの状態を共有するのはもちろん $foo = "オブジェクト破棄"; と片方に文字列を代入すると print $obj; 同様に文字列にかわってしまいます。 この本来の意味?であろう参照渡しとは実際 $fooに変数$objそのもののアドレスが保持されるという 解釈でよいのでしょうか? おくわしいかたご教授ください。

    • ベストアンサー
    • PHP
  • 使わなくなった変数に違う値を入れるのはマズイ?

    CやJAVAのような、厳密な型の存在しない言語(Perl、PHP、Javascriptなど)についての質問です。 プログラミングをしていて、途中である変数が要らなくなることがあります。これを、せっかく宣言したので別の値、それも型が違ったりプリミティブ型の値を入れてたのにオブジェクト型を入れるとか、そういう使い方をすることがあります。 例(Javascriptの場合) $hen = new Array(10); $hen[0] = 0; $hen[1] = 1; . . . for (i=0; i<10; i++) { print $hen[$i]; } //ここで配列henは要らなくなった。変わりに文字列が欲しい。 $hen = "String"; //せっかく変数henがあるので、これを入れ物として使う。 最近、C++の勉強をして、このようなケースで変数名との結びつきが無くなった変数の中身は、存在はするがアクセスする手段を失った「ゴミ」となるということを知りました。多くの言語も、同じような構造だとも知りましたが、同時に「ガベージコレクション」を装備している言語は、プログラムがその値が以降使われないと判断された場合は自動でその変数に割り当てているメモリを開放して処理速度向上を図る・・・とありました。では、例として挙げたケースでは、ガベージコレクションを装備していれば、ゴミは発生するがプログラムが自動でメモリを開放してくれるのでそこまで気にしなくても良い、という解釈で良いのでしょうか?私はPHPが得意なのですが、PHPは標準ではガベージコレクションを装備していないようなので、気をつけてプログラミングしようと思っているのですが。 余談ですが、「変数名と内容が一致しなくなるケースがある($arr = new Array();を後で$arr = "String";とするなど)からやめたほうが良い」という突っ込みはナシでお願いします。その点は承知していますので。

専門家に質問してみよう