コース一覧
    C言語中級 連結リスト・応用
    リストを全解放する

    C言語中級 連結リスト・応用

    C言語の連結リストと応用的なデータ操作を学び、実装でデータを扱うコースです。

    1
    連結リスト
    01. 配列の限界15分
    02. ノードを定義する15分
    03. 先頭に追加する15分
    04. リストを歩く15分
    05. 任意位置の挿入と削除15分
    06. リストを全解放する15分
    07. つくる リスト版成績管理15分
    08. 第5章クイズ10分
    2
    応用
    01. 動的な二次元配列15分
    02. コマンドライン引数15分
    03. バイナリ保存15分
    04. エラーの調べ方15分
    05. つくる 引数とバイナリ保存15分
    06. 第6章クイズ10分
    3
    総合制作
    01. リスト版を完成させる20分
    02. メモリバグ演習20分
    03. 自由拡張20分
    04. 完成と次のステップ10分

    リストを全解放する

    1回の free ではリストは片付かない

    動的配列なら、確保したのは大きな1枚なので free(list) の一発で終わりでした。リストは違います。ノードは1個ずつ別々に malloc した、別々の領域です。100人いれば100回の free が要ります。

    そして、ここには順番の罠があります。

    c

    while (head != NULL) {
        free(head);
        head = head->next;   /* 解放済みの領域を読んでいる */
    }

    free(head) を呼んだ時点で、その領域はもう自分のものではありません。head->next はそこにある値を読む操作なので、返した領域を読むことになります。多くの環境では値が残っていて動いてしまいますが、動くことと正しいことは別です。処理系がその領域を管理用に使い回した瞬間、次のノードとは無関係な値が入り、リストの途中で落ちるか、知らない番地を解放しようとします。

    次を控えてから解放する

    正しい形はこうです。

    c

    int free_list(struct Node *head) {
        struct Node *next;
        int freed = 0;
        while (head != NULL) {
            next = head->next;
            free(head);
            freed++;
            head = next;
        }
        return freed;
    }

    解放する前に、次の行き先を別の変数へ控えます。手すりから手を離す前に、次の手すりを掴んでおく、という順序です。

    解放したあとのポインタ

    free はポインタ変数の中身を消しません。渡した番地はそのまま残っていて、しかしその先はもう他人のものです。これをダングリングポインタと呼びます。呼び出し元では、リストを空にしたあと head に NULL を入れておきます。

    c

    free_list(head);
    head = NULL;

    NULL を入れておく利点は2つあります。うっかり使ったときに読み書きではなくその場で落ちるので原因が近くで分かること、そして free(NULL) は何もしないと決められているので、二重解放の事故が起きなくなることです。

    誰がいつ解放するのか

    リストのノードを作ったのは insert_head ですが、解放の責任を負うのはリストを持っている側です。関数が確保して呼び出し元が解放する形は珍しくなく、そのときは「この関数が返したものは呼び出し元が free する」という約束を、名前かコメントで残しておきます。約束が書かれていないヒープの受け渡しが、リークの発生源になります。

    では、解放した個数を数えながらリストを片付けましょう。

    要件

    1. 解放する前に次のノードの番地を別の変数に控える
    2. 全ノードを1つ残らず解放する
    3. 解放した個数を戻り値で返す
    4. リストが空のときは0を返す

    ヒント

    free したあとに head->next を読んではいけません

    ループの条件は head != NULL です

    空のリストではループが1回も回らず、0がそのまま返ります

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/08/07

    関連レッスン

    • つくる リスト版成績管理

      配列版の成績管理をリスト版に移行できるようになります。

    • 第5章クイズ

      連結リストの操作とつなぎ替えの理解を確認します。

    • 動的な二次元配列

      ポインタのポインタで表形式のデータを確保できるようになります。

    • リスト版を完成させる

      全機能をリスト前提で1本にまとめられるようになります。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • リスト順序付きで複数の値を扱うデータ構造
    • 配列サイズ固定の同型データの集まり
    • 処理計算や代入を表す長方形
    • 変数データに名前をつけて参照する仕組み
    • 関数処理に名前を付けて再利用できる単位
    • コメント# で1行コメント。
    • ヒープ親が子より常に大きい(最大ヒープ)または小さい(最小ヒープ)木構造。
    • 戻り値呼び出し元への返答を表す点線矢印
    main.c
    エディタを読み込んでいます

    メモ

    リストを全解放する

    ⌘S で保存