C#がメモリを管理する方法を学ぼうとしています。私は静的な要素にこだわっており、このテーマに関する多くのブログや記事を読んでいますが、満足のいく答えは見つかりません。
答えを見つけるのに役立つコードブロックを定義しましょう。
class myClass
{
static string myStr = "String Data";
static int myInt = 12;
}
皆さんがあなたの答えを共有する前に、この主題について私が知っている私の発見を共有させてください。自由に同意または反対し、正しい答えを見つけるのを手伝ってください。
私を混乱させているのは、このテーマに関して、インターネットで見つけたいくつかの答えです。
混乱番号1:
プログラムが起動すると、関連するすべてのアセンブリがAppDomainに読み込まれます。アセンブリが読み込まれると、静的フィールドを含むすべての静的コンストラクターが呼び出されます。それらはそこに存在し、それらをアンロードする唯一の方法は、AppDomainをアンロードすることです。
上記の行では、すべての静的要素がAppDomainに格納されていることが明示的に言及されています。それでは、なぜインターネット上の誰もが「静的」要素はヒープ/スタックに保存されると言うのでしょうか?
混乱番号2:
すべての静的変数は、参照型または値型のどちらで宣言されているかに関係なく、ヒープに格納されます。
すべての静的変数がヒープに格納されている場合。次に、なぜ値型の静的変数はスタックに格納されると言う人がいますか?
C#の静的変数のメモリ管理を理解するために、ドットをつなげてください。貴重な時間をありがとうございました:)
まず、これはすべて実装の詳細であることに注意してください。ランタイムが保証する唯一のものは:
それはほとんどそれです。それ以外はすべて実装の詳細です-仕様はスタック、ヒープ、またはその他のことを気にしません。ランタイムの実装次第であり、有効なランタイムは、必要に応じてすべてをスタックまたはヒープに置くことができます。また、レジスタを忘れないでください。
さて、あなたがすでに拾い上げた誤解のいくつかを見てみましょう:
TypeLoadException
が発生します(言うまでもなく、これは静的統計のデバッグを難しくします)。一部の人々は混乱する可能性があります。一部の人は、契約と実際の実装の違いを理解していません。単に何を話しているのか分からない人もいます。どちらが簡単かを知る簡単な方法があればいいのですが、そうではありません。疑わしい場合は、C#/ CLRの仕様にアクセスできますが、実際の現実ではなく、契約についてのみ説明しています。
管理メモリのポイントは、これらの実装の詳細を気にする必要がないことです。もちろん、あらゆる抽象化と同様にリークします。CPUのマイクロ命令、メモリキャッシングなど、さまざまなレイヤーや抽象化のすべてを通じて、物事が実際にどのようになっているのかを知ることは理にかなっています。しかし、それはrely onではありません-実装はいつでも変更でき、過去に何度もあります。
プロセスがRAMに読み込まれるたびに、メモリは(プロセス内の)スタック、ヒープ、静的(.NETでは実際にはヒープ内でのみ知られるヒープ内の特別な領域)の3つの領域に大まかに分けられます。高周波ヒープ)。
静的な部分は、「静的な」メンバー変数とメソッドを保持します。静的とは正確には何ですか?クラスのインスタンスを作成する必要がないメソッドと変数は、静的であると定義されます
続きを読む こちら 。
作成されたクラスのインスタンスがあり、すべての静的メンバーが初期化されています。
通常、静的クラスのメンバーはヒープに格納され、値型のメンバーは通常スタックに格納されます。
これは必ずしもそうである必要はありません。詳細については this blogを読んでください。
これは、C#の言語デザイナーの1人であるEric Lippertによるものです。
ブログは、通常の知識に反して、値型がスタック上にあり、参照型がヒープ上にあることを確信していないことを示していますが、通常はそうです。
仕様で指定されていないだけです。