• ベストアンサー

mallocとfree

struct list *p; /* 記憶領域の確保 */ if ((p = (struct list *) malloc(sizeof(struct list))) == NULL) { printf("malloc error\n"); exit(1); } とサンプルプログラムがあるのですが、if分の意味がわかりません。 また、mallocを使った場合freeで開放とあるのですが、 どういう意味なのかわかりません。 よろしければ、上記2つの点について教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

>freeはつまり何かにたとえると、 サーカスなどで動物が必要なため動物を使い、 使い終わったら、ジャングルなどに放すための 関数ということですか? そのように考えて、かまいません。但し、動物を使うためには、どこからか、借りてこなければ、いけませんので、動物協会から、借りてきて、使い終わったら、動物協会に返すと考えて下さい。 >さらに質問なんですが、なぜ、使い終わりましたと教えるのですか? 使い終わりましたと教える=動物を返すことになります。動物を返してあげないと、他のサーカス団が、動物をかりにきたとき、動物がいなくなるので貸すことが出来なくなります。 mallocで失敗するとNULLが返りますが、これはもう、貸し出せるメモリがありませんということです。動物を何匹か、貸して下さいと依頼がきても、動物がその数分いないので、貸し出せない状態と同じです。ですから、かりたら、使用後、すぐに返してあげないと、他のひとが、借りれなくなるので、返すようにして下さい。

その他の回答 (4)

  • rentahero
  • ベストアンサー率53% (182/342)
回答No.5

mallocとfreeに対する回答は既に出ているので省略。 if文の構文がちょっと複雑なので、そこの説明をしましょう。 if ((p = (struct list *) malloc(sizeof(struct list))) == NULL) { 外の括弧から順次外して説明していきます。 1.ifの次の括弧からNULLの後ろの括弧まで 簡単にするとif(XXX == NULL) {となります。 これはわかりますね?すなわち、XXXがNULL(ヌルポインタ)であれば、後に続くブロックを実行する、ということです。 2.pの手前の括弧から == の手前の括弧まで この中を簡単にすると(p = (struct list *) YYY)となります。これは代入文です。代入文も代入された値を左辺値として返却します。 すなわち、 p = (struct list *) YYY; if(p == NULL) { となっているのと同じ意味だということです。 3.次は括弧ではないですが、p = の次から==の手前二つ目の括弧まで これを簡単にすると(struct list *) malloc(ZZZ)となります。 前の括弧は型キャストです。malloc関数はvoid *型のメモリポインタを返却します。void *型のメモリはどんな型にも自動的にキャストされるので、実際には明示的にキャストしなくても、ポインタ変数に代入した時点で自動的にキャストされます。多分動作を理解をさせるために明示的にキャストしているのですが、結果的にはかえって複雑になっています。 mallocはメモリのバイト単位のサイズをsize_t型(実際にはint型のことが多い)の整数として渡しますので、ZZZは確保したいメモリサイズを表す整数です。 4.最後にmallocの引数です。(sizeof(struct list))となっています。 struct list型の構造体のサイズを取得しています。 結果として、どういうことになっているのかを日本語で書いてみると struct list型の構造体のメモリサイズ分のメモリをmalloc関数で確保する。malloc関数から返却されたポインタをstruct list型のポインタ変数pに代入し、さらにヌルポインタ定数NULLと比較する。比較した結果がtrue(p==NULL)であれば、後に続くブロックを実行する。 ちょっと説明がややこしいですが、2で書いたとおりに分割するとちょっとだけ理解がよいと思います。 分割した場合は以下のようになります。 struct list *p; /* 記憶領域の確保 */ p = (struct list *) malloc(sizeof(struct list)); if (p == NULL) { printf("malloc error\n"); exit(1); }

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

free関数は、malloc、calloc、およびreallocのいずれかで割り付けた領域を解放するために使用します。解放された領域は、malloc、calloc、またはreallocのいずれかで再利用することができるようになります。 注意しないといけないのは、free関数で領域を解放したとしても、実際にメインメモリの空きが増えるかどうか(つまりメモリがOSに返されるかどうか)は、規格上は規定されていません。ですから、そのプログラムの中では再利用できますが、並列に動いている他のプログラム(プロセス)で再利用できるとは限らないわけです。

  • ttyp03
  • ベストアンサー率28% (277/960)
回答No.2

#1さんではありませんがお答えします。 まず1行目の解説。 malloc は動的にメモリを確保する関数です。 malloc のパラメータは確保するメモリのサイズです。 つまり1行目の sizeof( struct list ) は、構造体 list のサイズ分ということになります。 malloc の戻り値は void* です。 これを構造体 list の領域として割り当てるために、struct list * 型にキャストをして p に格納しています。 if文は malloc が正常にできたかのチェックです。 さてfreeですが、確保したメモリは必ず解放しなければいけません。 そうしないと使うたびにメモリが減っていってしまいますからね。 これをメモリリークといいます。 http://e-words.jp/w/E383A1E383A2E383AAE383AAE383BCE382AF.html 子供のころから言われてると思いますが、「使ったものは片付けなさい」ということですね。 そうしないと部屋(メモリ)の中がどんどん狭くなってしまいます。 ちなみに開放ではなくて解放です。

回答No.1

malloc()はメモリ領域を確保する関数です。領域確保に失敗した場合、NULLを返します。 if文はmalloc()が失敗したかをチェックしています。 free()は確保したメモリを開放する関数です。malloc()で確保した領域をOSに使い終わりましたと教えるイメージでしょうか。

W07A09
質問者

補足

freeはつまり何かにたとえると、 サーカスなどで動物が必要なため動物を使い、 使い終わったら、ジャングルなどに放すための 関数ということですか? さらに質問なんですが、なぜ、使い終わりましたと教えるのですか?

関連するQ&A

  • malloc関数について。

    typedef struct a{ char *simei; int nenrei; }MEIBO; void main(void) { MEIBO a[5]; int wa; for(i = 0; i <= 4; i++ ) { a[i].simei = malloc(100 * sizeof(char) ); if( a[i].simei == NULL ) /* 領域確保に失敗したか */ { printf( "%dバイトの領域確保に失敗", 100 * sizeof(char) ); return 1; } printf("%d番目を入力してください\n",i+1); scanf("%s",&a[i].simei); printf("%s\n",a[i].simei); } C言語初心者です。これで入力したa[i].simeiが表示されないのですが、間違いを指摘していただけますでしょうか。宜しくお願いします。

  • このソースの意味を教えてください

    構造体を使ったリストを理解するためのソースで http://www9.plala.or.jp/sgwr-t/c/sec15-5.html のページに以下の関数が書いてありました。 自分はreturn p;とするのが自然であって、head = p;の意味が分かりません。それが不要な処理であるように思えます。 return head;としているのでその前にhead = p;は必要な処理ですが、無駄であって意味が無いように見えましたが、そのように書くのが自然なのでしょうか? head = p;の右に書いてあるコメントもおかしいと思うのですが、皆さんにはそのページのソースのその部分はコメントも含めて不自然さを感じないでしょうか? /*** リストにデータを登録 ***/ 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;     /* 新たな領域を先頭ポインタに */   return head; }

  • C free関数の開放について。

    独学でCを勉強し始めてる初心者です。 以下の構文で、最後に、 free(p); とあり、確保したメモリ「p」を開放していますが、 確保したメモリ「q」は開放しなくて良いのでしょうか? この場合は同じ部分のメモリを確保しているからqは開放しなくて良いということなんでしょうか…宜しくお願い致します。 #include <stdio.h> #include <stdlib.h> int main(void) { int *p; p=malloc(sizeof(int)*3); if(p==NULL) exit(1); p[0]=10; p[1]=20; p[2]=30; printf("%d\n",p[0]+p[1]+p[2]); free(p); return=0; }

  • C言語の自己参照型プログラムについて

    #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; /* 新たな領域を先頭ポインタに */ return 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; } } これを実行すると、 新しく入力された順にリストが表示されます。 そうではなく、キーの昇順に表示したいです。 どなたかそのように実行できるようにプログラムを書き換えてくれませんか? 図々しいですがよろしくお願いいたします。m(_ _)m

  • 線形リスト

    こんにちわ。今、大学で線形リストの勉強してるのですがよくわかりません。 ↓のプログラムで (1)10個のIDを受け取って受け取った順にリストを作るプログラム(各要素の値のアドレスとそのnextの値を表示してリストになっていることを確認する。) (2) (1)のプログラムを拡張して、リストを作ったあと、1から10までの間の整数nを入力として受け取り、リストのn番目の要素のIDを表示プログラムを書け。 の2つのことをしたいんですけど、どのようにすればいいのですか?どなたか回答おねがいします。 #include<stdio.h> #include<stdlib.h> struct list{ int ID; struct list *next; }; int main(int argc, char* argv[]) { struct list *top; top=(struct list *)malloc(sizeof(struct list)); //struct list 型の大きさの領域を1つ確保 //topがそこを指している状態にする //printf("IDを10個入力してください"); if(top == NULL){ //メモリが足りないと値がNULLになってします printf("メモリは確保できません\n"); exit(1); //強制終了。プログラムはココで終わってしまいます } top->next=NULL; top->ID=1; //ポインタtopが指している構造体のIDの値を変えている top->next=(struct list*)malloc(sizeof(struct list)); //もう1つ作ります //top->next==NULL (メモリ確保に失敗)の処理は省略 (top->next)->next=NULL; (top->next)->ID=5; //これで下図のような状態になります; return 0; }

  • リストの削除について(構造体)

    リストの削除のプログラムを実行して行ってみると、リストの削除処理中にプログラムが終わって変更後処理がうまく表示されません。どこが間違っているかが分からないしだいです。返答のほどよろしくお願いいたします。 #include<stdio.h> #include<malloc.h> #include<string.h> struct list{ char name[20]; int age; struct list *next; }; void main(void) { struct list *head, *p, *n, *old; char key[20]; /*ダミーノード作成*/ head = (struct list*)malloc(sizeof(struct list)); old = head; while(p = (struct list*)malloc(sizeof(struct list)), printf("name age入力\n"), scanf("%s %d", p -> name, &p -> age) != EOF){ old -> next = p; old = p; } free(p); old -> next = NULL; p = head -> next; printf("変更前リスト\n"); while(p != NULL){ printf("name:%s age:%d\n",p -> name, p -> age); p = p -> next; } printf("削除key入力(name)\n"); gets(key); n = head; while(n != NULL){ old = n; n = n -> next; //printf("n -> name %s\n", n -> name); if(strcmp(n -> name, key) == 0){ printf("%s削除\n", key); //printf("n -> name %s old -> name %s\n", n -> name, old -> name); old -> next = n -> next; } } p = head -> next; printf("変更後リスト\n"); while(p != NULL){ printf("name:%s age:%d\n", p -> name, p -> age); p = p -> next; } }

  • 単方向リスト

    #include<stdio.h> #include<stdlib.h> #include<string.h> struct Address{ char name[100]; char tel[100]; char email[100]; }; struct AddressList { struct Address addr; //データそのもの struct AddressList *next; //後続ノードへのポインタ struct AddressList *prev; }; struct AddressList *this,*last,*new,*first; struct Address *addr; /*--------ここからmain関数------------*/ int main(void){ int n,i; //何番目に入れるか? char quit[100]; //繰り返しを止める時に利用。 first=last=NULL; //まず初期化 addr =(struct Address *)malloc(sizeof(struct Address)); if(addr==NULL){ fprintf(stderr,"malloc:error\n"); exit(1); } while(-1){ printf("整数を入力してください。\n"); scanf("%d",&n); printf("名前を入力してください。\n"); scanf("%s",addr->name); printf("電話番号を入力してください。\n"); scanf("%s",addr->tel); printf("メールアドレスを入力してください。\n"); scanf("%s",addr->email); new =(struct AddressList *)malloc(sizeof(struct AddressList)); //新たに加えるリストの動的メモリー確保 if(new==NULL){ fprintf(stderr,"malloc:error\n"); exit(1); } new->addr=addr; //ここでエラーが発生します。 new->next=NULL; incompatible types in assignment とエラーがでます。 型はあってると思うんですが、、、 よろしくおねがいします。

  • malloc メモリリークについて

    #include<stdio.h> #include<stdlib.h> void alloconly(void) { const int sz=10; static int n=0; void *p; p=(void*)malloc(sz); if(p==NULL){ printf("動的確保不可 %d\n",n+1); printf("確保メモリサイズ %d byte\n",sz*n); exit(-1); } ++n; } int main(void) { for(;;){ alloconly(); } }と言うプログラムがある本に載っており、回答として   動的確保不可 *******(数字)   確保メモリサイズ *********byte(数字)となっていますが私の環境(Reshat Linux)では   強制終了します で終了してしまいます。原因が判らず困っています。ご解答願います。

  • mallocによる確保外の領域への参照

    構造体をmallocにより動的確保を行っていたのですが、例えば typedef struct _point{ int x, y; } point; point *pelem_point; pelem_point = (point *)malloc(sizeof(point)*5); このように、point型の構造体を5つ確保するとします。 しかし、 (pelem_point+100)->x = 1; (pelem_point+100)->y = 2; printf("%d\n", (pelem_point+100)->x); printf("%d\n", (pelem_point+100)->y); とやったら、確保していない100個先のところも構造体として利用できました。 なぜなのでしょうか。 自分の考えではこのようになりました。 mallocによりヒープ領域から適当な空いているメモリのアドレスが渡されるため、そこからはヒープ領域より先に、限りがあるまで進めてしまうために確保外のサイズにアクセスしても使えてしまっている。 また、mallocにより確保した場合は使用中のラベルがはられるため他に侵されることはないが、先の例のようにmallocによって確保してない場合はいくら使用できたとしても、空いているとコンピュータでは認識されるため、何かヒープ領域を使う場合に勝手に上書きされてしまう可能性がある。 しかし、この考えでも、なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。 わかる方いましたらよろしくお願いします。

  • メモリ動的確保について

    こんにちはです。 メモリの動的確保なのですが、 typedef struct DATA{ char name[256]; char pass[256]; int money; }BANK; void insert(BANK *p,int max); int main(){ int i; size_t st; BANK *person; person = (struct DATA *)malloc(sizeof(struct DATA)); //person = (struct DATA *)malloc(5); if(person == NULL){ printf("確保失敗\n"); exit(-1); } //memset(person,'\0',sizeof(struct DATA)); と、言う風に、記載ソースは途中ですがメモリをとりました。 mallocの後ろの部分ですが、sizeof(struct DATA)と5ではどうちがうのでしょう??2通りともコンパイルエラーはないです。 5は動的に最大5までとるって事はわかるのですが、struct DATAの方はいくつとるのです??いくつもで入力次第です? そして、動的したのにたいしてmemsetしたら実行エラー(コンパイルは通りました)おきました。動的にたいしてmemはダメなのでしょうか? アドバイスいただけたらありがたいです。宜しくお願いいたします。

専門家に質問してみよう