2011-06-21 19 views
1

最近、オブジェクト指向プログラミングに焦点を当てた入門ユニットを用意していましたが、C#のガベージコレクタに導入されました。より長く参照される。その後、私はデストラクタに導入され、オブジェクトが削除される直前にどのように呼び出されたのですか?同じクラスとガベージコレクションのデストラクタ内でのオブジェクトのインスタンス化

もちろん、私は思っていましたが、私はそれについて講師に尋ねることを思い出しませんでした。同じクラスのデストラクタ内でクラスのインスタンスを作成するとどうなりますか?

C#の例

class Person{ 
~Person(){ 

    Person p = new Person(); 
    Console.WriteLine("Person destroyed"); 

} 
} 

class Program{ 
static void Main(string[] args){ 
    Person p = new Person(); 
} 
} 

私は、ビューのより理論的な観点からこれにアプローチしたいと思いますので、私はおそらく、とにかく理解できないであろうから、私はそれを試して(この段階では)消極的です私はいくつかの理論を持っています。また、私は今、私の通常のコンピュータではないよ;)

  • 人〜人()新しい人が作成されるたびとして、そのデストラクタを呼び出して、新しいを作成するために起こっている、再帰的に起こっていますPerson ad infinitum、または何らかのメモリ関連例外が発生するまで。その後、メインは決して終了しません。
  • コンパイラは文句を言うでしょう(すべてのシナリオにこのオプションを追加するのは良い考えです)。
  • どういうわけか、ある種の「デストラクタースキップ」が発生します。すなわち、オブジェクトの破壊は順番に呼び出されないので、どちらもコンストラクタではありません。

類似の質問があります。ガベージコレクタの役割が、もはや参照/不要になっているオブジェクトを削除することである場合、上記のような状況はガベージコレクタのない環境でどのように処理されますか?

答えて

4

私はここに本当の謎がないと思う。

これは「再帰的」ではありません。ただちに逆参照される管理対象ヒープ上に新しいオブジェクトをチャッキングするだけです。したがって、ガベージコレクションの候補になります。

最終的にはガベージコレクタが再びラウンド来る、再度操作をトリガーするなど

再帰ないことを - より多くのチェーンのような。しかし、最終的にはそれぞれPersonがメモリから削除されます。

ガベージコレクタから、あなたが公正を果たしていないと不平を言うメールが送信されます。

C++については、そこに建設/破壊が起こってから、その後に非常に不気味なコンピュータがあるので、私の推測はスタックオーバーフローです。

あなたの次の論理的な考えが「ランタイム/言語でこれをやめてはいけませんか? - いいえ。問題の言語やランタイムは、そうでなければ悪用されると思われる何かをやめることを止めるためのものではありません。それはあなたがプログラマーであると確信して、あなたがそれをやっていないことを確認します。

これは、アプリケーションのシャットダウンシナリオ(以下のコメントを参照)では.Netランタイムが自己利益を発揮しないため、最終的にこれらのファイナライザの処理を停止してシャットダウンを停止することになります。ファイナライザはあなたの利益のためであり、ランタイムのものではありません。

+0

私はこの単純なプログラムの実行がどのように停止するのか知りたいのですか?明らかにファイナライザを連鎖してコンソールに出力し始めます。どのようにランタイムは実際にこのプロセスを終了しますか(通常の終了は私が知る限りファイナライザを実行します)。 – InBetween

+0

@InBetween - 異常終了の場合は問題ありません。協調シャットダウンでは、.Netランタイムがアプリケーションがボールを再生していないと判断した場合、最終的にファイナライザの処理を停止し、すべてをリリースします。ファイナライザは、他のものよりもあなたのプログラムにとってとても礼儀正しいものです。より現代的なWindowsオペレーティングシステムでは、プロセスが終了するとリソースも解放されます。 –

2

さらに興味深い点は、オブジェクトがファイナライザで実際にresurrect itselfになることです。

class Foo 
{ 
    static public List<Foo> ZombieFoos = new List<Foo>; 

    ~Foo() 
    { 
     ZombieFoos.Add(this); 

     // Now there is a reference to this instance again (in the list).. 
     // The GC will not reclaim this instance.. huzzah we have been resurrected!! 
    } 
} 

でもリモートで推奨しない

...

+1

問題を引き起こすすばらしい方法! –

+1

私はC#の場合は分かりませんが、Javaでは危険で分かりにくく、オブジェクトは復活しますが、プロパティは変わります。特に、ファイナライザは各オブジェクトに対して一度だけ呼び出されるため、オブジェクトは一度戻ってくることになりますが、繰り返しはありません。これは驚くべきことです(オブジェクトが最初は死んだ...)。あなたはJavaの事例についてこの記事を読むことができます[オブジェクトの最終化とクリーンアップ](http://www.javaworld.com/javaworld/jw-06-1998/jw-06-techniques.html) –

+1

@DavidRodríguez - dribeas同じC#でtrueの場合、オブジェクトをファイナライズするために手動で再登録する必要があります。しかし、Javaの場合と同様に、これは危険であり、* Cでもあまりにも混乱しています。私はそれがゾンビオブジェクトだからです!またはあなたがそれを呼びたいと思っているイエスの教室 – MattDavey

1

あなたは、実際には、原因システムは、GCで99.9時間であることをことができます。ヒープ0の収集を開始するGCのために、すべてのPersonオブジェクトによって十分な量のメモリを取得するだけです。

関連する問題