none
関数内で確保したオブジェクトの生存期間について RRS feed

  • 質問

  • 初歩的な質問ですいません。

    関数内で確保したオブジェクトを戻り値として戻した場合、そのオブジェクトの生存はどの時点まで保証されるのでしょうか?

     

    例えば以下のように関数内で配列を確保し、それを戻り値として戻したとします。

    class hoge
    {
      public byte[] ToByte()
      {
        byte[] ret = new byte[10];
        //処理//
        return ret;
      }
    }
    
    
    この関数を利用して次の処理を記述したとします。
    class fuga
    {
      public void Question()
      {
        hoge h = new hoge();
        byte[] data = h.ToByte();
        //dataを使用した処理//
        return;
      }
    }
    
    

    この場合、ToByte()関数内で確保したオブジェクトは、C言語での自動変数的な振る舞いをすると解釈した場合、関数から抜けた段階で保証されなくなってしまいますが、

    一方で参照をreturnしていますので、依然としてそのオブジェクトは参照されているとしてガーベジコレクションの対象とはならないようにも思えます。

    このような処理の場合、関数内で確保したオブジェクトの生存はどこまで保証されるのでしょうか?

     

    2011年4月21日 1:53

回答

  • そもそも、C++ とかでも

     

    char* GetBytes() {
      char* addr = new char[4];
      return addr;
    }
    

    が問答無用で delete されたりはしませんよね。

    unsafe なら C# でもスタックに配列を作れますが、もちろんこれは外部に持ち出せません。

    2011年4月21日 2:56
  • > 関数内で確保したオブジェクトの生存はどこまで保証されるのでしょうか?

    最後に参照しているところまでです。参照が失われた時点で保障されない状態になります。ただし、ソースコード的に到達可能(スコープ内)であることと参照が有効であることは別ですので、C言語の auto 変数のように、関数が抜けるまで有効ではありません。

    {
      // 参照を開始
      var data = h.ToByte();
    
      // data を使用してるので、ここは保証されている
      Console.WriteLine(data.ToString());
    
      // こちらの行の時点では、もう data を参照していないので
      // この時点で data はもう保障されていない
      Console.WriteLine("end.");
    }
    
    
    2011年4月21日 4:01

すべての返信

  • .NET Frameworkではメモリの管理が自動的に行われます。まだ使用しているオブジェクト(どこかから参照されているオブジェクト)が消えてしまうと困ります。つまり、消えてしまうのはそのオブジェクトがどこからも参照されなくなった時です。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年4月21日 2:14
    モデレータ
  • そもそも、C++ とかでも

     

    char* GetBytes() {
      char* addr = new char[4];
      return addr;
    }
    

    が問答無用で delete されたりはしませんよね。

    unsafe なら C# でもスタックに配列を作れますが、もちろんこれは外部に持ち出せません。

    2011年4月21日 2:56
  • > 関数内で確保したオブジェクトの生存はどこまで保証されるのでしょうか?

    最後に参照しているところまでです。参照が失われた時点で保障されない状態になります。ただし、ソースコード的に到達可能(スコープ内)であることと参照が有効であることは別ですので、C言語の auto 変数のように、関数が抜けるまで有効ではありません。

    {
      // 参照を開始
      var data = h.ToByte();
    
      // data を使用してるので、ここは保証されている
      Console.WriteLine(data.ToString());
    
      // こちらの行の時点では、もう data を参照していないので
      // この時点で data はもう保障されていない
      Console.WriteLine("end.");
    }
    
    
    2011年4月21日 4:01
  • みなさんありがとうございます。

    気になっていた点が解決し、すっきりしました。

     

    2011年4月21日 8:19