2017-07-25 5 views
-1

私はDisposeパターンについて読んでいたのですが、どうすればmemory is allocatedが出てきました。以下はhttp://codebetter.com/karlseguin/2008/04/28/foundations-of-programming-pt-7-back-to-basics-memory/の引用です。ほとんどのデータがヒープになる場合、スタックメモリの重要性/役割は何ですか?

メモリ割り当て
....
....
この規則の唯一の例外は、タイプを参照するために属する値の種類があります - 例えばUserクラスのIdプロパティが進みますヒープと、Userクラス自体のインスタンス

これはまた、ここでスタックオーバーフローについて言及されています。 memory allocation for value type inside reference type in .net

私の理解は、宣言されている場所に関係なくすべての値の型がスタックになるということでした。今は間違っています。下のコードでは、iがヒープになります。リンクに従ってスタックにはない。これは、MyClassがヒープになり、その値のすべての型とともに参照型になるためです。

class MyClass() 
{ 
    int i = 5; 
} 

[OK]をクリックすると、クラスの一部ではない値の型だけがスタックメモリに移動します。右?しかし、C#のようなDot Net言語のほとんどすべてがクラスの中にあります。それでは、スタックメモリには何がありますか?

このanswerは、ヒープに行く値の種類を説明しています。

これが当てはまる場合、スタックメモリにはほとんど、あるいはまったく何もありません。

私は何かを誤解していると思う。

ほとんどすべてのデータがヒープメモリに移行する場合は、スタックメモリの重要性と役割は分かりません。

説明してください。


次の2つの記事では、簡単な方法でメモリ管理について詳しく説明しています。

https://blogs.msdn.microsoft.com/ericlippert/2009/04/27/the-stack-is-an-implementation-detail-part-one/

https://blogs.msdn.microsoft.com/ericlippert/2009/05/04/the-stack-is-an-implementation-detail-part-two/

+0

スタックは、主にローカル変数用であり、コールツリー内の変数を追跡します。 – juharr

+2

Eric Lippertの[The Stack Is Implementation Detail]を読んでください(https://blogs.msdn.microsoft.com/ericlippert/2009/04/27/the-stack-is-an-implementation-detail-part-one/) 。 –

+0

スタックはプッシュしてポップするので便利です。それは小さな利点ではありません。だからこそスタックがあるのです。メモリ割り当てシナリオでも役に立つことがあります。また、そこからEric Lippertの説明が届きます。 –

答えて

9

"スタック" と "ヒープ" としてそれについて考えてはいけません。 短期記憶長期記憶と考えることができます。スタック上に何が起こっているのか、何がヒープ上にあるのかを知ることは非常に簡単になりました。 変数の有効期間は、現在のメソッドのアクティブ化よりも長くなっていますか?はいの場合、短命ではなく、ヒープ上に移動する必要があります。そうであれば、にスタックできます。例えば

:それは長い方法の活性化よりも続かないので

class C { 
    void M() { 
    string s = Whatever(); 
    Something(s); 
    } 
} 

ローカル変数sは、短期プールに行くことができます。

これで、文字列が参照型なので、確かにヒープ上に置かれます。そして、そうではありません。 文字列はヒープ上にありますが、変数には文字列が含まれていません。文字列は参照型であるため、の変数がに、の参照がスタックに格納されます。 を参照するものはヒープ上にありますが、参照自体は値であり、スタックに入ることができます。

何かの種類が格納されている場所を判断することをやめてください。タイプは無関係です。値型または参照型の変数は、短期間プールの場合は短期プールになり、短期プールの場合は長期プールに移動する必要があります。

は今何

class C { 
    void M() { 
    int i = Whatever(); 
    X(() => i) 
    } 
} 

については、今私がスタックに行くことができますか?いいえXは渡されたデリゲートのコピーを格納することができ、デリゲートはiの値を知る必要があるので、変数Mのアクティブ化よりも長く生きる必要があるので、iは長期プールになります。 iはヒープ上にあります。

再び、intであるという事実は完全に無関係です。それは変数であり、長い時間をかけているので、ヒープになります。

クラスのフィールドや配列の要素はどうですか?それらは変数です。クラスインスタンスまたは配列インスタンスが存続している限り、それらは存続します。したがって、その存続期間は予測できません。したがって、長期プールに入ります。

なぜ私たちは短期間プールと長期間プールを持っていますか?短期プールのガベージコレクタは、極端にはであり、長期プールのガベージコレクタに比べて高速で安価です。したがって、短期間のプールで変数を生成するオプションが必要です。つまり、ライフタイムが短くの場合です。

+0

"...ヒープ上にあるものは..." - なぜですか?それは常にヒープで割り当てられることが保証されていますか?もし 'Tuple '(参照型)を持っているのであれば、それはなぜヒープに配置する必要がありますか? –

+2

@LucaCremonesi:言及されているものは*寿命が短いことが分かっていない*。さて、メソッド内に特定の参照が作成され、メソッドをエスケープしないことがわかっているので、メソッドが返ってから使用されないシナリオがあります。そのような場合、CLR *はスタック上の何かへの参照を生成することができます。現在の実装ではそうではありません。参照型に対して1つのアロケータとコレクタを用意する方が安価で簡単です。しかし、原則として、短期間の参照型のインスタンスには異論はありません。 –

関連する問題