本文へスキップ
BecomeCoder

Rustコース · 第3章 メモリの土台 ― スタックとヒープ · レッスン12

スタックとヒープ

ローカル実施

導入

プログラムが使うメモリは、大きく スタックヒープ の2つの領域に分かれています。所有権を理解するには、この2つの違いを体でわかっている必要があります。ここは丁寧にいきましょう。

説明

スタック(stack) は「積み重ね」を意味します。皿を積むように、データを上へ積み(push)、使い終わったら上から取る(pop)——最後に置いたものを最初に取り出す構造です。

  • 速い:常に「一番上」に置くだけなので、置き場所を探す必要がありません。
  • サイズが固定でなければならない:スタックに置く値は、コンパイル時に大きさが分かっている必要があります。i32(4バイト)や bool(1バイト)、要素数の決まった配列などです。
  • 関数が呼ばれると、その関数のローカル変数がスタックに積まれ、関数が終わるとまとめて自動でお片付けされます。

ヒープ(heap) は「山積み」のイメージ。サイズが実行時にしか決まらない/後から変わるデータを置く、自由な領域です。

  • 柔軟:好きな大きさを、実行中に確保できます(例:ユーザー入力の文字列、要素が増減するリスト)。
  • 少し遅い:空いている場所を探して確保し、使い終わったら解放する手間がかかります。
  • ヒープにデータを置くと、その場所を指す「ポインタ」(住所のようなもの)が返ってきます。このポインタ自体はサイズが固定なので、スタックに置かれます

図にすると、こういう関係です。

graph LR
    subgraph stack["スタック(固定サイズ・高速)"]
        n["n: 42"]
        ptr["ptr ●"]
    end
    subgraph heap["ヒープ(可変サイズ・自由)"]
        data["ユーザーが入力した長い文字列……"]
    end
    ptr -->|指す| data
  • n: 42 のような固定サイズの値は、スタックに直接置かれます。
  • 大きさが変わりうるデータはヒープに置かれ、スタックにはそこを指すポインタが置かれます。

なぜこの区別が所有権に効くのか? スタックの値は関数の終わりに自動で片付きます。問題はヒープです。ヒープに確保したデータは「いつ解放するか」を誰かが決めなければなりません。ここで登場するのが所有権です——Rust は「ヒープ上のデータには、必ず1人の所有者(スタック上の変数)がいる。所有者がいなくなったら、そのヒープデータを解放する」というルールでこれを解決します。次章の主役です。

試すには

いまは図とイメージを掴めれば十分です。「固定サイズ=スタック/可変サイズ=ヒープ+ポインタ」という対応と、「ヒープの解放タイミングをどう決めるかが問題」という点を覚えておいてください。次のレッスンで、実際の値がどちらに置かれるかを見ます。