スタックとヒープの違い:メモリ領域の使い分けを比較
動いているプログラムは、データのために、主に2つのメモリ領域を使います。スタックは、関数呼び出しのフレーム、つまりローカル変数、引数、戻りアドレスを保持します。自動で管理され、非常に速いですが、小さく、関数の呼び出しの寿命に縛られます。ヒープは、mallocやnewなどで、プログラムが明示的に要求したメモリを保持し、解放されるまで生き続けます。ヒープは柔軟で大きいですが遅く、メモリリークや断片化が起こるのもここです。
| 項目 | スタック | ヒープ |
|---|---|---|
| 用途 | 関数呼び出しのフレーム。ローカル変数、引数、戻りアドレス | 関数より長く生きる、またはサイズが事前にわからない、動的に確保するデータ |
| 確保の方法 | 自動。呼び出しと復帰のたびに、スタックポインタが動く | 明示的。mallocとfree、newとdelete、またはガベージコレクタ |
| 速度 | 非常に速い。ポインタを動かすだけ | 遅め。アロケータが空きのブロックを探し、記録を管理する |
| 寿命 | 関数が戻るまで | メモリが解放される(またはガベージコレクションされる)まで |
| 大きさ | 限りがある(通常はスレッドごとに数MB) | 使えるメモリの量だけが上限 |
| 配置 | 通常は高いアドレスから下向きに伸びる | 通常は低いアドレスから上向きに伸びる。両者は互いに向かって伸びる |
| 断片化 | なし | ありうる。確保と解放を繰り返すと、使えない隙間が残る |
| スレッド | スレッドごとに専用のスタックがある | すべてのスレッドで共有するので、アロケータはスレッドセーフでなければならない |
| よくあるエラー | 深い再帰や大きなローカル配列によるスタックオーバーフロー | メモリリーク、解放後の使用、二重解放、メモリ不足 |
数値は代表的な目安で、世代や製品によって異なります。