昔から、変数 (値型または参照型) がどこに格納されるかを正確に知りたいと思っていました。スタックまたはヒープに配置されますか?
同じことに関するEric Lippert の記事を読みました。
好奇心から、私が望んでいたのは、私が理解したことを同じように相互検証することです。同じためのツールはありますか?または、.NET プログラムが実行されている間に、どの変数がスタックに格納されるかを知るようになりますか? そして、どれがヒープに保存されますか?
ありがとう
昔から、変数 (値型または参照型) がどこに格納されるかを正確に知りたいと思っていました。スタックまたはヒープに配置されますか?
同じことに関するEric Lippert の記事を読みました。
好奇心から、私が望んでいたのは、私が理解したことを同じように相互検証することです。同じためのツールはありますか?または、.NET プログラムが実行されている間に、どの変数がスタックに格納されるかを知るようになりますか? そして、どれがヒープに保存されますか?
ありがとう
ストレージがスタックとヒープで分割されていると考えるのは便利な抽象化であり、うまく機能します。しかし、それはもっと複雑で、.NET プログラムの変数には 6 つの異なる格納場所があります。
ここで選択するツールはデバッガーです。変数が格納されている場所を正確に表示できます。それには、マシンコードがどのように機能するかについての洞察が必要です。Debug + Windows + Disassembly を使用して、マシン コードを確認します。また、プログラムのリリース ビルドを確認し、デバッグ時にもコードが最適化されるように設定を変更することも重要です。[ツール] + [オプション]、[デバッグ]、[全般] で、[モジュールの読み込み時に JIT 最適化を抑制する] オプションのチェックを外します。これで、マシン コードがユーザーのマシンで実行される方法が表示されます。
すべてを理解するために事前に知っておくべきこと:
参照型のオブジェクトは GC ヒープに格納されます。参照を格納する変数には、値型の値と同じ種類のストレージの選択肢があります。
値型の値またはオブジェクト参照には、次の 6 つの保存場所があります。
後半の 3 つの箇条書きは、複雑になる箇所であり、マシン コードを調べて格納場所を調べる必要がある理由です。これは実装固有であり、ジッターの種類が重要です。また、ジッター オプティマイザーを有効にしているかどうかによって大きく影響を受けます。ここで適切な選択を行うことは、パフォーマンスにとって非常に重要です。大まかな概要 (ARM ジッターをスキップ):
最初の 2 つのメソッド引数は、x86 ジッターの CPU レジスタに格納され、インスタンス メソッドの値が含まれます。x64 ジッタは 4 つのレジスタを使用します。浮動小数点プロセッサ レジスタは、x86 では Single および Double 型の変数を渡すために使用され、x64 では XMM レジスタが使用されます。
関数の戻り値は、適合する場合は EAX または RAX レジスタを使用して CPU レジスタに返されます。浮動小数点値の場合は ST0 です。収まらない場合、呼び出し元は値用にスタック フレームのスペースを予約し、その値へのポインターを渡しました。
ジッタ オプティマイザは、ローカル変数を CPU レジスタに格納する機会を探します。レジスターが不足しているために強制的にレジスターをスタック フレームにスピルバックする場合があります。
これらの実装の詳細には、いくつかの観察可能な副作用があります。