動的メモリ割り当て — malloc と free
このトピックを終えると
スタックとヒープメモリの違い、動的割り当てが必要な理由、そしてメモリリークがなぜ発生するかを理解します。
2種類のメモリ
プログラムが使用するメモリは、主に スタック (Stack) と ヒープ (Heap) の2つの領域に分けられます。
高いアドレス ┌──────────────┐
│ スタック │ ← 関数呼び出しのたびに自動的に割り当て/解放
│ ↓ 下へ │
│ │
│ │
│ ↑ 上へ │
│ ヒープ │ ← プログラマが直接割り当て/解放
低いアドレス └──────────────┘| スタック | ヒープ | |
|---|---|---|
| 割り当て | 自動(関数呼び出し時) | 手動 (malloc) |
| 解放 | 自動(関数終了時) | 手動 (free) |
| サイズ | 小さく固定(通常数MB) | 大きく可変(RAMの制限) |
| 速度 | 非常に速い | やや遅い |
| 用途 | ローカル変数、関数引数 | サイズが不定のデータ |
なぜ動的割り当てが必要なのか
スタックに変数を作成する場合、サイズを コンパイル時に 知っておく必要があります。
int arr[100]; // 100個 — コンパイル時に決定しかし、ユーザーに「何個のデータを入力しますか?」と尋ねた場合、プログラムが実行されるまでにはわかりません。このような場合に動的割り当てを使用します。
int n;
printf("何個? ");
scanf("%d", &n);
int *arr = malloc(n * sizeof(int)); // 実行中にn個割り当てmalloc (memory allocation) は、ヒープで要求されたバイト数分のメモリを割り当てます。
malloc と free
#include <stdlib.h>
// 割り当て
int *data = malloc(5 * sizeof(int));
// 使用
for (int i = 0; i < 5; i++) {
data[i] = i * 10;
}
// 解放
free(data);
data = NULL; // 安全のため NULL に設定malloc がメモリを割り当てたら、使用でき、使い終わったら free で返さなければなりません。free を行わない場合、そのメモリはプログラムが終了するまで解放されません。
メモリリーク
void process() {
int *data = malloc(1000000 * sizeof(int));
// データ処理...
if (error) {
return; // free を行わずに終了!
}
free(data);
}この関数がエラーで終了した場合、free が実行されません。100万個の int (約 4MB) が解放されません。この関数が1000回呼び出されると、4GB がリークします。これが メモリリーク (memory leak) です。
メモリリークは、プログラムがすぐに終了しないため危険です。徐々にメモリを消費し、最終的にシステム全体が遅くなり、OOM (Out of Memory) で終了します。サーバープログラムでは、数日後に突然終了する原因になることもあります。
高度な言語の解決策 — ガベージコレクション
Python、JavaScript、Java、Go は、ガベージコレクター (GC) が自動的に解放します。
def process(): data = [0] * 1000000 # 関数が終了すると、data を参照する変数がなくなる # → GC が自動的にメモリを回収プログラマが free を呼び出す必要はありません。GC が「このメモリを指している変数がもうない」ことを定期的にチェックし、回収します。
代償があります。
| 手動 (C) | 自動 (Python/Java) | |
|---|---|---|
| メモリリークの可能性 | 高い(プログラマのミス) | 低い(GC が処理) |
| パフォーマンス | 予測可能 | GC 実行時に一時的に停止する可能性がある |
| コードの複雑さ | 高い(free の管理) | 低い(気にしなくてよい) |
Rust は、第3の道を選択しました。GC もなく、手動による free もなく、コンパイラが変数のライフサイクルを追跡し、自動的に解放コードを挿入します。
核心
スタック は自動的に割り当て/解放され、ヒープ はプログラマが直接管理します。
mallocでヒープに割り当て、freeで解放 — 忘れると メモリリーク。 高度な言語は GC でこの問題を自動的に解決しますが、なぜメモリ管理が必要なのか を知っておくことが、CS の基礎です。