C# new演算子の舞台裏:メモリ確保からコンストラクタ呼び出し、GCまで徹底図解

2025年7月22日

C#などのオブジェクト指向言語における new 演算子のライブ実行時の動作は、以下のような段階的なプロセスを経て行われます。これは、実行時(runtime)におけるメモリ上での振る舞いのことを指します。

new演算子の実行により行われる一連のライブ処理:

図に出てくる “型ポインタ” は、.NET ランタイムが そのヒープ上オブジェクトがどの型(クラス)であるかを識別するために埋め込んでいるポインタです。


型ポインタが担う役割

役割具体的な働き
動的ディスパッチ仮想メソッド/インターフェイス メソッド呼び出し時、型ポインタ経由でメソッドテーブル(vtable)を見つけ、正しい実装アドレスへジャンプします。
ランタイム型チェックis, as, GetType() などで「この参照は Player 型か?」を判定するとき、まず型ポインタを比較します。
ガーベジコレクションGC は世代別や型ごとのヒープウォーク時に型サイズ・フィールド情報を調べる必要があります。その入口になるのが型ポインタです。
リフレクションtypeof(Player) で得られる System.Type オブジェクトも、このポインタが示すメタデータにリンクしています。

ざっくり図示

[オブジェクトヘッダ | 型ポインタ]──┐
                              │  ← 型ポインタが指す
                        [メソッドテーブル/型メタデータ]
  • オブジェクトの先頭(ヘッダ直後)に配置される 1 ポインタ分の領域。
  • C++ で言えば “vptr” に近く、CLR 用語では Method Table pointer と呼ばれることもあります。

1. 型のメタデータの解決(型情報のロード)

  • 実行時、指定されたクラスの型(Type)がまだ読み込まれていなければ、メタデータ(型定義)がアセンブリからロードされ、型情報(Typeオブジェクト)が生成されます。
  • .NETでは、これが「Type System」によって処理され、JIT(Just-In-Time)コンパイル前の準備として重要です。

2. ヒープ領域へのメモリ確保(インスタンスの確保)

  • new によって、マネージドヒープ(managed heap)に必要なサイズ分のメモリが割り当てられます。
  • このサイズは、そのクラスが持つインスタンスフィールドの合計サイズ+管理用オーバーヘッド(例:型情報へのポインタやGCヘッダ)です。

3. フィールドのゼロ初期化

  • 確保されたメモリ領域は、すべてゼロクリア(zeroed)されます。
  • これは、C#の仕様により全てのフィールドが既定値(0, null, falseなど)で初期化されるためです。

4. コンストラクタの呼び出し

  • new の後に指定されたコンストラクタが実行され、明示的な初期化が行われます。
  • このタイミングで this が有効になり、初期化ロジックが走ります(例:フィールドに値を代入する処理など)。

5. 参照の返却

  • 最終的に、作成されたインスタンスのヒープ上のアドレスを指す参照が返され、変数に代入されます。

💡ライブ挙動の視覚的イメージ(Visual Studioの視点)

Visual Studioの「ローカルウィンドウ」「ウォッチウィンドウ」などで追跡すると、以下のように見えます:

Person p = new Person("Alice");
  1. Person型がロードされる(初回)
  2. p には最初 null(または未定義)が表示される
  3. new により、ヒープに Person オブジェクトが確保され、p がその参照を持つようになる
  4. p.Name == “Alice" など、コンストラクタによる値の反映が確認できる

🧠 補足:new の実行とGC(ガベージコレクション)の関係

  • 作成されたオブジェクトはマネージド環境下でGCが管理します。
  • 参照が失われると、一定時間後にGCのスキャン対象となり、次のタイミングで解放されます。
  • ライブ実行では、new は常に「割り当てるだけで解放はしない」挙動であることがポイントです。

🔬まとめ

ステップ処理内容ライブの動作視点
1型のメタデータ読込型情報がロードされる
2ヒープメモリの確保メモリが確保される
3ゼロ初期化フィールドが既定値になる
4コンストラクタ実行明示的な初期化が行われる
5参照の返却変数がインスタンスを指す

さらに詳細な観察を行いたい場合は、Visual Studioのメモリ診断ツールや、.NET CLR Memoryパフォーマンスカウンタ、WinDbg などの低レベルデバッガを用いると、ライブでのオブジェクト割り当て状況を追跡できます。

訪問数 3 回, 今日の訪問数 1回

C#,メモリ管理

Posted by hidepon