質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • C

    4641questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

free()関数について、こんがらがっています。正しい意見を教えてください。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 467

sanchu52

score 164

先日free()関数について質問をしたんですが、free()関数の中身が間違っているという意見と
free()関数の中身についての説明を頂いたのですが、どちらが正しいのか、私には判断が出来ません。正しい意見を教えてください。
前橋和弥著のポインタの完全制覇には一度free(fp)したポイントにアクセスしてはいけないと
ありました。
わたしの参考にしているプログラムに以下のようなfree()関数があるんですが、どうなんでしょうか。
普通openしたファイルを閉じるときにfree()関数でメモリを開放すると認識しているんですが、malloc()関数を使った時もfree()関数でメモリを解放するんでしょうか。
よろしくお願いいたします。

コード
コード
#include <stdio.h> 
#include <string.h>
#include <stdlib.h>

struct list {
    int key;                // キー 
    char name[20];            // 名前 
    struct list *next;        // 次のデータへのポインタ 
};

struct list *add_list(int key, char *name, struct list *head);
void show_list(struct list *p);
void free_list(struct list *p);

int main(void)
{
    struct list *head;        // 先頭ポインタ 
    char name[20];
    int key = 0;

    head = NULL;            // 先頭ポインタにNULLを設定 

    printf("キーと名前(MAX:19文字)を入力(終了:CTRL+Z)\n");

    while (scanf("%d %s", &key, name) != EOF) {
        head = add_list(key, name, head);    // リストにデータを登録 
    }
    show_list(head);        // リストの表示 

    free_list(head);        // リストの開放 

    return 0;
}

// リストにデータを登録 
struct list *add_list(int key, char *name, struct list *head)
{
    struct list *p;

    // 記憶領域の確保 
    if ((p = (struct list *) malloc(sizeof(struct list))) == NULL) {
        printf("malloc error\n");
        exit(EXIT_FAILURE);
    }

    // リストにデータを登録 
    p->key = key;
    strcpy(p->name, name);

    // ポインタのつなぎ換え 
    p->next = head;        
    // 今までの先頭ポインタを次ポインタに 
    // 新しいデータの次のポインタに headのアドレスをつなぐ。
    // p->nextが次を指すようにする。新たな領域を先頭ポインタに
    head = p;            
    // 新たな領域を先頭ポインタに 
    // headにpのアドレスを代入してpを先頭ポインタにする。
    // 先頭ポインタ(head)新しくなったNODEに沿って移動していく
    return head;
    // 最後に代入されたデータがheadになるのでそのアドレスを返す。

}

// リストの表示 
void show_list(struct list *p)
{
    while (p != NULL) {    // 次ポインタがNULLまで処理 
        printf("%3d %s\n", p->key, p->name);
        p = p->next;
    }
}

//リストの開放 
void free_list(struct list *p)
{
    struct list *p2;

    while (p != NULL) {     // 次ポインタがNULLまで処理 
        p2 = p->next;
        free(p);
        p = p2;
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KSwordOfHaste

    2018/01/20 16:43

    一つ前のQ&Aを指しているなら「free()関数の中身が間違っているという意見」は見当たりません。何かの勘違い?質問者さんの言い間違い?それとも一つ前のQ&Aではない?自分はこの質問を見て混乱してしまいました。

    キャンセル

回答 3

checkベストアンサー

+1

while (p != NULL) {     // 次ポインタがNULLまで処理 
  p2 = p->next; // freeの前にnextが指す場所をとっといて
  free(p); // (pをfreeするとp->nextが読めない。アブナイトコダッター)
  p = p2; // んでもって無事次の要素を辿ることができるね♪
}

普通openしたファイルを閉じるときにfree()関数でメモリを開放すると認識している

ファイルはfopenで開けてfcloseで閉じる。
メモリはmallocで獲得しfreeで開放する。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/20 16:38

    ありがとうございます。いつも恥しい質問で恐縮しています。

    キャンセル

0

open()で開いたファイルを閉じるのはclose()です。
malloc()で確保したメモリを解放するのはfree()です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/20 16:35

    ありがとうございます。そうでした勘違いしていました。
    初心者なのでご勘弁を。

    キャンセル

  • 2018/01/20 16:37

    いえいえ、少なからずお役に立てたのならよかったです。

    キャンセル

0

普通openしたファイルを閉じるときにfree()関数でメモリを開放すると認識している 

違う。

free()関数はmalloc(),calloc(),realloc(),aligned_alloc()によって確保されたメモリーを開放するために用います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/20 16:42

    いつもありがとうございます。皆さんに指摘して頂きたすかりました。

    キャンセル

同じタグがついた質問を見る

  • C

    4641questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。