導入
プログラムが動くとき、変数の値はコンピュータの メモリ(RAM)のどこかに置かれます。使い終わったメモリは解放して返す必要があります。返し忘れれば無駄に消費し続け(メモリリーク)、まだ使っているのに返してしまえばプログラムが壊れます。この「いつ確保して、いつ解放するか」の管理は、実はとても難しく、長年バグの温床でした。
説明
メモリ管理には歴史的に大きく3つの方式があります。
① 手動管理(C / C++) — プログラマが自分で「確保」と「解放」を書きます。
確保して……使って……自分で解放する(malloc / free、new / delete)
速くて自由ですが、人間はミスをします。よくある事故は次の3つです。
- 解放し忘れ → メモリリーク(使わないメモリを抱えたまま)。
- 二重解放(同じメモリを2回解放) → クラッシュ。
- 解放後に使用(dangling / use-after-free) → 解放済みの領域を読み書きし、深刻なバグやセキュリティ脆弱性に。
② ガベージコレクション(Java / Python / Go / JavaScript など) — 「もう誰も使っていないメモリ」を、実行中のプログラムが自動で探して回収します。
プログラマは解放を書かない。裏で GC が動いて掃除してくれる
安全で楽ですが、GC が動く間プログラムが少し止まる(一時停止・オーバーヘッド)ことがあり、リアルタイム性やメモリ効率が求められる場面では不利になります。GC 自体を動かすランタイムも必要です。
③ 所有権(Rust) — Rust は上の2つとは違う第三の道を選びました。「どの値を、いつ解放してよいか」を、コンパイル時にコンパイラが判断できるようにルールを決めたのです。
プログラマは解放を書かない。GC もいない。
コンパイラが「所有権のルール」に沿って、解放するコードを自動で挿入する
この結果、Rust は次を同時に達成します。
- GC なし(実行時の一時停止も、重いランタイムもない)→ C/C++ 並みに速い。
- メモリ安全(解放忘れ・二重解放・解放後使用がコンパイル時に防がれる)。
graph TD
q["メモリを誰が管理する?"]
q --> c["手動(C/C++)<br/>速いが事故が起きやすい"]
q --> g["GC(Java/Go等)<br/>安全だが実行時コスト"]
q --> r["所有権(Rust)<br/>速い かつ 安全<br/>=コンパイル時に解決"]
「速さ」と「安全」はこれまでトレードオフでした。Rust の所有権は、その両立を狙った仕組みです。次のレッスンから、その舞台となる「スタック」と「ヒープ」を見ていきます。