スタックとヒープを “コード+図” で一気に理解する

― SharpLab の Inspect でメモリを覗きながら学ぶ超入門記事 ―


1. このブログでわかること

学習ポイント何ができる?
スタック の正体関数呼び出しごとにフレームが積まれる様子を図とダンプで確認
ヒープ の役割参照型オブジェクトが倉庫(ヒープ)に置かれ、変数は住所だけ持つことを体験
値型 vs 参照型int と Person を同じ関数内で扱い、メモリ配置の差を可視化
Boxingint を object に入れるとヒープに 24 B の箱ができることを確認
デバッグ代替Inspect.Stack と Inspect.MemoryGraph を“擬似ブレークポイント”として使う方法

2. まずは図でざっくりイメージ

  • :スタック
    • 呼び出しが深くなるとフレーム(青)が増える
    • 高位アドレス → 低位アドレス に向かってポインタが移動
  • :ヒープ
    • オブジェクトの箱が好きな場所に置かれる
    • 変数は“住所メモ”で箱を指す矢印を持つ

この図を念頭に、次のコードを動かしてみましょう。


3. 実験用コード(SharpLab にコピペ)

using SharpLab.Runtime;   // Inspect を使うには必須

class Program
{
    static void Main()             // フレーム #1
    {
        "=== Main フレーム ===".Inspect();   // 見出しだけ
        Inspect.Stack("Frame Dump");         // Main フレーム全体

        Foo();
    }

    static void Foo()              // フレーム #2
    {
        "=== Foo フレーム ===".Inspect();
        Inspect.Stack("Frame Dump");         // Foo 追加後

        Bar();
    }

    static void Bar()              // フレーム #3
    {
        "=== Bar フレーム ===".Inspect();
        Inspect.Stack("Frame Dump");         // Bar 追加後

        int x = 5;                           // 値型 → スタック
        Inspect.Stack(x);                    // x を撮る

        Person p = new Person();             // 参照型 → ヒープ
        Inspect.MemoryGraph(p);              // p とヒープ箱を撮る
    }
}

class Person { }

動かし方

  1. SharpLab (https://sharplab.io) を開く
  2. 上記を貼り付け → 右上 Results → Run → Run ▶︎
  3. 右ペインに
    • ラベル (Inspect: === Main …)
    • スタックダンプ(Pointer to System.String … 行など)
    • System.Int32 行(x = 5 が載った証拠)
    • MemoryGraph 行(p → Person 箱)が順に出る → 図と照合してみる

4. 出力の読み方

出力行示すもの図との対応
Inspect: === Main/Foo/Bar ===ラベル見出し各フレームの開始点
Pointer to System.String …ダミー文字列ポインタフレームが“1枚増えた”目印
System.Int32 005 …x = 5 本体がスタックに載る青ブロック「ローカル変数」行
p: Person ref → Person: Personスタックの参照とヒープ箱の矢印ベージュ箱+矢印部分

ポイント:Inspect.Stack(x) と Inspect.MemoryGraph(p) を“擬似ブレークポイント”として挿入するだけで、メモリのスナップショットが撮れる。


5. スタック vs ヒープ 早見表

観点スタックヒープ
管理LIFO/速い/自動解放GC が参照確認/確保・回収はコスト高
寿命関数終了で消える参照が途切れるまで残る
容量数 MB/スレッドプロセス空きメモリ全体
主な用途値型・引数・小さな一時変数参照型・大きな配列・boxing 値型

6. まとめ

  1. スタックは“メモ書き”を積む作業台。関数が終われば自動で片づく。
  2. ヒープは住所付き倉庫。長生きオブジェクトやクラスの箱を置く。
  3. SharpLab でも Inspect.* を差し込むだけ でフレームの増減 / 値型配置 / ヒープ確保 が一目でわかる。
  4. 本格的にステップ実行したい場合は Visual Studio など IDE へ。

これで 図・コード・実行結果 がリンクし、「メモリで何が起きているか」をイメージできるようになったはずです。まずは自分のコードに Inspect.Stack を 1 行入れて、スタックの変化を観察してみてください。

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

C#,メモリ管理

Posted by hidepon