2009-07-15 27 views
4

.netフレームワークでさまざまな型(値と参照)にメモリがどのように割り当てられるかを説明できる高度な記事がありますか。.netフレームワークでの値型と参照型のメモリ割り当て

たとえば、値の型はスタック上に領域が割り当てられていますが、その値はどのように管理されていますか?

また、ヒープ内で参照タイプがどのように管理され、実際の値が格納されているかについても説明します。

答えて

1

メソッドが呼び出されるとき、値型によって必要とされる領域の量は、事前に分かっています(これは、クラスのように参照型は、コンパイラ)。このスペースはスタックに割り当てられ、メソッド呼び出しの間だけ使用可能です。新しいメソッド呼び出しのたびに、スタック上で使用されるメモリが増加し、メソッドが終了すると元のレベルに縮小します。

参照型はヒープに割り当てられます。ヒープは、基本的にその目的のために使用されるメモリのブロックです。ヒープに格納されるオブジェクトは、主に、オブジェクトに割り当てられたメモリに格納されているオブジェクトのフィールドです。したがって、値型フィールドはヒープ上のオブジェクトの "内側"に格納されます。参照型フィールドは、参照されるオブジェクトへの参照(またはポインタ)として格納されます。ヒープ上のメモリはガベージコレクションによって管理されます。それは複雑な対象ですが、ヒープ上の未使用オブジェクトに割り当てられたメモリは解放され、ガベージコレクタによって定期的に再利用されるということです。

10

。 「値の型がスタックに割り当てられている」というあなたの主張であっても、正しいものではありません。例えば:

class Foo 
{ 
    int x; 
} 

intは値型であり、それはクラスではFooのインスタンスの残りのデータと共に格納されるため、xの値は、常にヒープになります。

さらに、匿名関数とイテレータブロックのキャプチャされた変数は、人生を厄介にします。

私にはarticle about C# heap/stack memoryがありますが、便利なことがありますが、"The stack is an implementation detail"のEric Lippertのブログ記事もお読みください。特に、将来のC#コンパイラは、メソッドの開始時に作成されたインスタンスへの参照を保持するためだけにスタックを使用して、ヒープにすべてのローカル変数を格納することを決めることができます。すべて。

3

値の型は、定義されているところでは "割り当てられます"。そこ で値型の値に合わせてメモリ内のクラス/構造体を拡大し、その構造体のフィールドとして、クラス/構造体で

  • :その手段は、あなたがそれを定義する場所に依存して何

  • 最適化に応じて、メソッド、スタック、またはレジスタ、または生成クラスのフィールド( "クロージャ"を使用する場合)のローカル変数として
  • メソッドのパラメータとして、スタック最適化に応じてレジスタとして、または

参照型は、2つの値の並べ替えです。参照型は中心的にポインタであり、ポインタ型の値は値型としての "割り当て"と同じ規則に従いますが、一度値を格納すると、つまり、オブジェクトへの参照。そのオブジェクトは別の場所のヒープ上にあります。

つまり、参照変数自体は値型として「割り当てられていますが、参照するオブジェクトはヒープ上にあります。

クラスからオブジェクトを作成するときに、そのクラスのすべてのフィールドに+そのスペースのオーバーヘッドを合わせるために、ヒープにスペースが割り当てられます。

Jon Skeetがこの件について記事を書いていることを思い出しているようですが、私は彼が本当にすぐに答えを出してくれると確信しています。

+3

そこに彼は私の答えをタイプしている間にあった。 –

2

参照型は常にヒープになりますが、値型は常に宣言された場所に移動します。値の型がメソッドの外部で宣言されているが参照型の中に宣言されている場合は、ヒープの参照型に配置されます。

関連する問題