• ベストアンサー

free()について

free()について int *x; x = malloc(4*3); *x = 1; *(x+1) = 10; *(x+2) = 100; free(x); としたとき free(x)ではどうして確保した分のメモリを開放できるのですか? 引数xから最初の4バイト分はわかりますが、ぴったり確保した分を開放できるのが理解できません

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

  • ベストアンサー
  • anmochi
  • ベストアンサー率65% (1332/2045)
回答No.1

malloc(4*3)というのは、4×3=12バイトのメモリブロックを確保し、その先頭場所を返すというものです。決して「4バイトを3つ」ではありません。で、xは、上記の「先頭場所」に対してラベルを貼るイメージです。 *(x+1) = 10; にて、「xというラベルが指し示している場所から4バイト(int 1個分)後ろの場所にintで10という値を設定する」という処理をしたとしても、xがメモリブロックの先頭を指している事には変わりません。 *(x+2) = 100; も同様です。 上の2つを、 *x++ = 10; *x++ = 100; などとしてはいけません。x(というラベルが指し示す場所)自体が変化してしまうからです。 xがmallocで確保したメモリブロックの先頭位置をずっと指し示しているから、free(x)でそのメモリブロックを開放できるのです。freeはintを開放するのではなく、あくまでmallocでガスっと一括確保された12バイトのメモリブロックを開放する事を理解してください。

cern5100
質問者

お礼

回答ありがとうございます。 mallocで確保していることを覚えていてそれを開放するんですね。 引数のxの情報から全て判断しているのかと思ってました。 イメージがわきました。

その他の回答 (5)

  • orfenok
  • ベストアンサー率0% (0/1)
回答No.6

僭越ながら実装レベルで回答させて頂きます。 アドレスとサイズのペアを内部でテーブルとして持っているからだと思います。 C言語で実装してみると、容易に実現できると思います。 // memory.cpp typedef struct { char* pAddress; // mallocで返すアドレス size_t uSize;  // mallocで指定されたサイズ } MEM; static MEM s_table[SIZE_MAX]; // メモリ管理テーブル static int s_num; // テーブルの要素数 void* malloc( size_t uSize ) {  void* pAddress = 空いているヒープを探す();  // 管理テーブルに記録  s_table[ s_num ] = pAddress;  s_table[ s_num ] = uSize;  s_num++;  return pAddress; } void free( void* pAddress ) {  int i;  for ( i=0; i < s_num; i++ ) {   // テーブルと一致するアドレスを探す   if ( pAddress == s_table[i].pAddress ) {    size_t uSize = s_table[i].uSize; // ★これが開放すべきサイズ★    ヒープ開放();    break:   }  } } ※実際にはテーブルは配列ではなく双方向リストなどで実装し、開放の際前後の空き領域とマージして断片化を考慮していると思います。

cern5100
質問者

お礼

回答ありがとうございます。 難しくて理解するのが大変ですが考えてみます。

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.5

malloc時に確保した領域の「先頭アドレス」と「確保量」のデータを何かしらの手段(OSによって異なる)で持っているためです。 なので、free()には「先頭アドレス」を正しく渡さなければいけません。 また、freeが利用するのは先頭アドレスだけで型情報は使っていない、というのは既出の通りです。

cern5100
質問者

お礼

回答ありがとうございます。 そこのところを大きく誤解していました。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

> 引数xから最初の4バイト分はわかります xがint *だから、int分の4バイト分、と考えたのでしょうが、freeの引数はvoid *型です。解放したい領域のポインタ(≒先頭アドレス)を受け取るだけです。 C++だと、引数の型によって処理を分ける機能がありますが、Cにはありません。 そのポインタが何型へのポインタ(int *なのか、char *なのか、double *なのか)はわかりません。 したがって > 引数xから最初の4バイト分はわかります というのは「誤解」です。 ついでに言うと、intが4バイトというのも環境依存です。2バイトだったり8バイトだったりするかもしれません。 mallocに「4」と決めつけて使うのではなく、sizeofを使いましょう。

cern5100
質問者

お礼

回答ありがとうございます。 誤解していました。 ポインタの中身はint *もchar *もまったく同じなんですか? それで引数として渡されてしまったあとはもう単なるアドレスだけしかわからなくなって しまうのですか?

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

>引数xから最初の4バイト分はわかります わかる理由は何ですか? >ぴったり確保した分を開放できるのが理解できません 理解できない理由がわかりません。

cern5100
質問者

お礼

回答ありがとうございます。 >>引数xから最初の4バイト分はわかります > わかる理由は何ですか? ポインタにもint 型のポインタなど型があるので そこで開発環境orコンパイラorなんらかのシステム?が判断して 先頭のバイトのアドレスさえわかれば4バイト分把握できると勝手に思い込んでいたのですが その解釈は間違ってましたか? 良かったらそこのあたりも教えていただけたらと思います。 つまり int a; int *p; p = &a; としたときどうして*pによってaの値を参照できるかということなど >>ぴったり確保した分を開放できるのが理解できません >理解できない理由がわかりません。 確保した領域の先頭アドレス”だけ”から何バイト確保したかなぜわかるのかが わかりませんでした。

cern5100
質問者

補足

すみません誤解してたようです。 下から読んでいたので次の回答読んでませんでした。

回答No.2

システムの管理上は、 (1)malloc(4*3)で確保された領域に関する情報を別途持っている。 (2)malloc(4*3)で確保された領域の-4バイトのところにサイズ情報を持っている。 等が考えられます。 おそらく(1)がシステム的には一般的です。 この情報から解放された領域(アドレス、サイズ、属性等)をもっと大きな(ユーザ空間の)管理エリアに戻すことになると考えられます。 要するにできる仕組みが組み込まれているのです。

cern5100
質問者

お礼

回答ありがとうございます。 まだ詳しくは理解できませんが、一番わからなかったところと だいたいの管理イメージは理解わかりました。 自分のイメージでは引数に重みを置きすぎていました。

関連するQ&A

  • freeで開放される範囲

    お世話になります 例えばある構造体を、 typedef struct {  char* yoso1;  int yoso2; } kozotai; とし、これをmallocで確保した後中身のポインタにもmallocし、 kozotai* test = (kozotai*)malloc(sizeof(kozotai)); test->yoso1 = (char*)malloc(128); freeで開放すると、 free(test); 中の要素の指すメモリも開放されるでしょうか? 今はどちらか分からないので、 free(test->yoso1);free(test);としています。。。

  • メモリの開放について

    いつもお世話になっております。 メモリ開放のお作法について教えてください。 int* p ; p = (int*)malloc( 100 * sizeof( int ) ) ;  ※ p = (int*)malloc( 100 * sizeof( int ) ) ;  ※ p = (int*)malloc( 100 * sizeof( int ) ) ; free(p); このような記述をした場合、※の付いている2行でメモリ確保した 領域は開放されるのでしょうか。 (メモリ確保に失敗した場合の処理は省略してます。) よろしくお願いします。

  • malloc関数 free開放とはなんですか?

    malloc関数を用いてメモリを確保した後、 必ずfreeで開放を行わなければならないですよね? この開放とはどういう意味なのでしょうか?

  • 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/C++言語のメモリについて

    C言語でメモリを2種類?に分けると、スタックとヒープがあります。 ヒープは mallocなどで確保し、freeで解放しますがスタックは解放する必要がありません。 そのスタックは通常、何バイトまで可能なのでしょうか? あと関数外のファイルの先頭に int[1000000];とした場合、このメモリはmallocで確保していませんが、 どこに作られるのでしょうか? 私のパソコンはメモリが2GBでWindows2000ですが、CやC++で最大、何バイトまでメモリが使えますか? また、一番多くメモリを確保できるなら、OSはなんでも構いません。 解釈等も間違っていたらご指摘していただきたいです。

  • mallocとfree

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

  • free()について

    free()についてです。 よろしくお願いします。 ある構造体Aがあったとして その構造体Aの中に構造体Bのポインタが あったとします。 typedef struct{ char b; short c; } B_t; typedef struct { int a; B_t *bbb; } A_t; この構造体をプログラム中でポインタで扱い mallocで領域確保している場合に(A,B共に) Aをfree()した場合は、Bも開放されるのでしょうか? 以下、質問のサンプルです。 A_t *aaa; aaa = (A_t *)malloc(sizeof(A_t)); aaa->bbb = (B_t *)malloc(sizeof(B_t)); : : free(aaa); /* ←これで、aaaのメンバであるbbbは */ /* 開放されるのでしょうか? */ よろしくお願い致します。

  • メモリ操作関数『malloc(),free()』

    /*10バイトのメモリ領域を確保し、その領域に文字列"Allocate"を代入せよ。*/ /*ただし、確保した領域は、プログラム終了までに開放すること。*/ #include<stdio.h> #include<stdlib.h> void main(void) { char *ptr; ptr = (char *)malloc(10); printf("Allocate\n"); free(ptr); } 今、ライブラリ関数を勉強しています。 この問題をとりあえず作ってみて、実行も成功したのですが、10バイトのメモリ確保の数値を変えても、何も変わらないため本当に問題の要求どおりのプログラムが作れているのか謎です。 間違っているなどのアドバイス宜しくお願いします。

  • free()への引数について

    下位にて動的に確保した領域を解放するのは以下のように すればよいのでしょうか?また解放されているか確認する方法はあるのでしょうか? void main(){ char *p = 0x00; if (0 != exaMalloc(&p)) { printf("err\n"); exit(); } free(&p); } int exaMalloc(**p) { *p = malloc(10); if (*p == 0x00) { return -1; } return 0; }

  • C++ 最適なメモリ確保

    画像処理をするために実験的にC++でプログラムを書いています。 malloc関数でBMP画像の画素位置を、画像画素分確保するだけのint型配列を作成するにはどうしたらよいでしょうか。 因みに、入力画像の解像度は640x480です。 一番左下の画素を(x,y)=(0,0)として考えています。 ある条件の画素に該当する画素座標を、下のStackX,StackYにx,y成分ごとに格納していくものです。 //////// int *StackX = (int *)malloc(sizeof(int)*100000); int *StackY = (int *)malloc(sizeof(int)*100000); //////// 上のように書くと、途中でクラッシュしてしまいます。 ですが、大目にメモリをとって //////// int *StackX = (int *)malloc(sizeof(int)*10000000); int *StackY = (int *)malloc(sizeof(int)*10000000); //////// で実行すると、最後まで動いてくれます。