一覧へ

「動的メモリ割り当て — mallocとfree」

「プログラム実行中にメモリを動的に割り当てる理由、スタックとヒープの違い、メモリリークがなぜ危険なのかを学びます。」

中級
|
10
|
検証済み (2026-07)
動的メモリmallocfreeヒープメモリスタックメモリメモリリーク
進捗0/23 (0%)

動的メモリ割り当て — malloc と free

このトピックを終えると

スタックとヒープメモリの違い、動的割り当てが必要な理由、そしてメモリリークがなぜ発生するかを理解します。


2種類のメモリ

プログラムが使用するメモリは、主に スタック (Stack)ヒープ (Heap) の2つの領域に分けられます。

text
高いアドレス ┌──────────────┐
          │    スタック       │ ← 関数呼び出しのたびに自動的に割り当て/解放
          │   ↓ 下へ        │
          │              │
          │              │
          │   ↑ 上へ        │
          │    ヒープ       │ ← プログラマが直接割り当て/解放
低いアドレス └──────────────┘
スタックヒープ
割り当て自動(関数呼び出し時)手動 (malloc)
解放自動(関数終了時)手動 (free)
サイズ小さく固定(通常数MB)大きく可変(RAMの制限)
速度非常に速いやや遅い
用途ローカル変数、関数引数サイズが不定のデータ

なぜ動的割り当てが必要なのか

スタックに変数を作成する場合、サイズを コンパイル時に 知っておく必要があります。

c
int arr[100];  // 100個 — コンパイル時に決定

しかし、ユーザーに「何個のデータを入力しますか?」と尋ねた場合、プログラムが実行されるまでにはわかりません。このような場合に動的割り当てを使用します。

c
int n;
printf("何個? ");
scanf("%d", &n);

int *arr = malloc(n * sizeof(int));  // 実行中にn個割り当て

malloc (memory allocation) は、ヒープで要求されたバイト数分のメモリを割り当てます。


malloc と free

c
#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 を行わない場合、そのメモリはプログラムが終了するまで解放されません。


メモリリーク

c
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) が自動的に解放します。

python
def process():
data = [0] * 1000000
# 関数が終了すると、data を参照する変数がなくなる
# → GC が自動的にメモリを回収

プログラマが free を呼び出す必要はありません。GC が「このメモリを指している変数がもうない」ことを定期的にチェックし、回収します。

代償があります。

手動 (C)自動 (Python/Java)
メモリリークの可能性高い(プログラマのミス)低い(GC が処理)
パフォーマンス予測可能GC 実行時に一時的に停止する可能性がある
コードの複雑さ高い(free の管理)低い(気にしなくてよい)

Rust は、第3の道を選択しました。GC もなく、手動による free もなく、コンパイラが変数のライフサイクルを追跡し、自動的に解放コードを挿入します。


核心

スタック は自動的に割り当て/解放され、ヒープ はプログラマが直接管理します。 malloc でヒープに割り当て、free で解放 — 忘れると メモリリーク。 高度な言語は GC でこの問題を自動的に解決しますが、なぜメモリ管理が必要なのか を知っておくことが、CS の基礎です。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...