malloc関数によって確保されたメモリをfree関数を使って解放しなければコンピュータは利用できるメモリが減ってしまうためプログラムの実行速度が遅くなることがあります

ソーラー「ふう」


アレサ「ふう」


ソーラ「・・・」


アレサ「・・・」



ソーラー「もう1つmalloc関数をつかってメモリを確保する例をみていこうかな?」


アレサ「どのような例題が示されるか楽しみですの😊


malloc関数は興味深い関数ですの」



ソーラー「次のプログラムでは


malloc関数をつかってメモリを確保して


そのメモリに文字列データ"neko"を格納した後


free関数によってそのメモリを解放し


さらに


malloc関数をつかってメモリを確保して


そのメモリに文字列データ"nyao"を格納した後


free関数によってそのメモリを解放しています


さて どのようなコンパイル結果になるかな~」


#include <stdio.h>

#include <stdlib.h>


int main(void) {


char *p;


p = (char *)malloc(sizeof(char)*5);


if (p == NULL) {

printf("メモリは確保されませんでした。");

}


else {

printf("メモリは確保されました。\n");

printf("そのメモリのアドレスは %pです。\n", p);

}


printf("%p\n", &p[0]);//ここでp[0]のアドレスをもとめています

printf("%p\n", &p[1]);//ここでp[1]のアドレスをもとめています

printf("%p\n", &p[2]);//ここでp[2]のアドレスをもとめています

printf("%p\n", &p[3]);//ここでp[3]のアドレスをもとめています

printf("%p\n", &p[4]);//ここでp[4]のアドレスをもとめています


p[0]='n';

p[1]='e';

p[2]='k';

p[3]='o';

p[4]='\0';/*ここにナル文字を格納することでポインタ変数pを使って

文字列データ"neko"をメモリに格納したことになります*/


printf("%c\n", p[0]);

printf("%c\n", p[1]);

printf("%c\n", p[2]);

printf("%c\n", p[3]);

printf("%c\n", p[4]);


printf("%s\n", p);

/*ポインタ変数pを使って

文字列データ"neko"をコマンドプロンプト画面に表示します*/


free(p);

//メモリを解放しました


char *a;


a = (char *)malloc(sizeof(char)*5);


if (a == NULL) {

printf("メモリは確保されませんでした。");

}


else {

printf("メモリは確保されました。\n");

printf("そのメモリのアドレスは %pです。\n", a);

}


printf("%p\n", &a[0]);//ここでa[0]のアドレスをもとめています

printf("%p\n", &a[1]);//ここでa[1]のアドレスをもとめています

printf("%p\n", &a[2]);//ここでa[2]のアドレスをもとめています

printf("%p\n", &a[3]);//ここでa[3]のアドレスをもとめています

printf("%p\n", &a[4]);//ここでa[4]のアドレスをもとめています


a[0]='n';

a[1]='y';

a[2]='a';

a[3]='o';

a[4]='\0';/*ここにナル文字を格納することでポインタ変数aを使って

文字列データ"nyao"をメモリに格納したことになります*/


printf("%c\n", p[0]);

printf("%c\n", p[1]);

printf("%c\n", p[2]);

printf("%c\n", p[3]);

printf("%c\n", p[4]);


printf("%s\n", a);

/*ポインタ変数aを使って

文字列データ"nyao"をコマンドプロンプト画面に表示します*/


free(a);


return 0;


}


ソーラー「コンパイルっ」


コンパイル結果


メモリは確保されました。

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

e

k

o

(空白)

メモリは確保されました。

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

y

a

o

(空白)


アレサ「ソーラーさん 同じアドレスのメモリ


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44


がmalloc関数により確保されて


free関数を使って解放されています」


ソーラー「面白いね。


このプログラムでは


malloc関数により確保された先頭のメモリのアドレス010D4B40


p = (char *)malloc(sizeof(char)*5);


により

ポインタ変数pに格納されているんだよね。


そうすると


char *pにより作製された


char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリに


アクセスすることができるようになるんだ



同様に


malloc関数により確保された先頭のメモリのアドレス010D4B40


a= (char *)malloc(sizeof(char)*5);


により

ポインタ変数aに格納されているね。


そうすると


char *aにより作製された

char型の配列変数

a[0]

a[1]

a[2]

a[3]

a[4]


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリに


アクセスすることができるようになるんだ


このプログラムでは


malloc関数を使って


確保した

アドレス

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリに


char *pにより作製された


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

を使って


p[0]='n';

p[1]='e';

p[2]='k';

p[3]='o';

p[4]='\0';


文字列データ"neko"を格納した後


これらの

アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリを解放しています。


さらにその後


再び


malloc関数を使って


確保した

アドレス

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリに


char *aにより作製された


配列変数

a[0]

a[1]

a[2]

a[3]

a[4]

を使って


a[0]='n';

a[1]='y';

a[2]='a';

a[3]='o';

a[4]='\0';



文字列データ"nyao"を格納した後


これらの

アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリを解放しています。


アレサ これがmalloc関数の基本的な使い方となっているんだよ。


つまり


このプログラムの目的が


コンパイル結果


メモリは確保されました。

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

e

k

o

(空白)

メモリは確保されました。

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

y

a

o

(空白)


を表示することだったとすると


メモリは確保されました。

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

e

k

o

(空白)


を表示した時点で


アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリに


文字列データ"neko"を格納している必要はないので


アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリを


コンピュータが利用できないよう


確保しておく必要はないよね




そこで


free(p);


を実行することにより



アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリを解放し


アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリを


コンピュータが利用できるようにしたというわけなんだ


だから


malloc関数により


再び


アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリを


確保することができ


新たに文字列データ"nyao"を格納できたんだよ。


アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリの


メモリ解放を行わなくても


もちろん


malloc関数をつかって


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリとは


別のメモリを確保することはできるよ


ただし


アドレス番号

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

の付いたメモリは確保されたままとなるので


プログラムの実行が終了するまで


コンピュータは


それらの5バイト分のデータ容量を持つメモリ


を利用できないってわけだ


次のプログラムをみてよ。


#include <stdio.h>

#include <stdlib.h>


int main(void) {


char *p;


p = (char *)malloc(sizeof(char) * 5);


if (p == NULL) {

printf("メモリは確保されませんでした。");

}


else {

printf("メモリは確保されました。\n");

printf("そのメモリのアドレスは %pです。\n", p);

}


printf("%p\n", &p[0]);//ここでp[0]のアドレスをもとめています

printf("%p\n", &p[1]);//ここでp[1]のアドレスをもとめています

printf("%p\n", &p[2]);//ここでp[2]のアドレスをもとめています

printf("%p\n", &p[3]);//ここでp[3]のアドレスをもとめています

printf("%p\n", &p[4]);//ここでp[4]のアドレスをもとめています


p[0] = 'n';

p[1] = 'e';

p[2] = 'k';

p[3] = 'o';

p[4] = '\0';/*ここにナル文字を格納することでポインタ変数pを使って文字列データ"neko"をメモリに格納したことになります*/


printf("%c\n", p[0]);

printf("%c\n", p[1]);

printf("%c\n", p[2]);

printf("%c\n", p[3]);

printf("%c\n", p[4]);


printf("%s\n", p);

/*ポインタ変数pを使って

文字列データ"neko"をコマンドプロンプト画面に表示します*/


//free(p);を記述してメモリ解放をおこないません👈


char *a;


a = (char *)malloc(sizeof(char) * 5);


if (a == NULL) {

printf("メモリは確保されませんでした。");

}


else {

printf("メモリは確保されました。\n");

printf("そのメモリのアドレスは %pです。\n", a);

}


printf("%p\n", &a[0]);//ここでp[0]のアドレスをもとめています

printf("%p\n", &a[1]);//ここでp[1]のアドレスをもとめています

printf("%p\n", &a[2]);//ここでp[2]のアドレスをもとめています

printf("%p\n", &a[3]);//ここでp[3]のアドレスをもとめています

printf("%p\n", &a[4]);//ここでp[4]のアドレスをもとめています


a[0] = 'n';

a[1] = 'y';

a[2] = 'a';

a[3] = 'o';

a[4] = '\0';/*ここにナル文字を格納することでポインタ変数aを使って文字列データ"nyao"をメモリに格納したことになります*/


printf("%c\n", a[0]);

printf("%c\n", a[1]);

printf("%c\n", a[2]);

printf("%c\n", a[3]);

printf("%c\n", a[4]);


printf("%s\n", a);

/*ポインタ変数aを使って

文字列データ"nyao"をコマンドプロンプト画面に表示します*/


free(a);


return 0;


}


コンパイル結果


メモリは確保されました。

そのメモリのアドレスは01634B40です。

01634B40

01634B41

01634B42

01634B43

01634B44

n

e

k

o

(空白)

メモリは確保されました。

そのメモリのアドレスは01634B78です。

01634B78

01634B79

01634B7A

01634B7B

01634B7C

n

y

a

o

(空白)

(メモリの使用状況によって取得するアドレスの値は変化していきます)



ソーラー「このプログラムでは


p= (char *)malloc(sizeof(char) * 5);


が実行されたとき


malloc関数は


01634B40

01634B41

01634B42

01634B43

01634B44


のアドレス番号の付いたメモリを確保しています。


その後


01634B40

01634B41

01634B42

01634B43

01634B44


のアドレス番号の付いたメモリの


メモリ解放を行わなかったので


a = (char *)malloc(sizeof(char) * 5);


が実行されたとき


malloc関数は


01634B40

01634B41

01634B42

01634B43

01634B44


のアドレス番号の付いたメモリとは


別のメモリ


01634B78

01634B79

01634B7A

01634B7B

01634B7C


を確保しているんだ。


そして

printf("%p\n", &p[0]);

printf("%p\n", &p[1]);

printf("%p\n", &p[2]);

printf("%p\n", &p[3]);

printf("%p\n", &p[4]);

printf("%c\n", p[0]);

printf("%c\n", p[1]);

printf("%c\n", p[2]);

printf("%c\n", p[3]);

printf("%c\n", p[4]);

printf("%s\n", p);

が実行されて


コンパイル結果


メモリは確保されました。

そのメモリのアドレスは01634B40です。

01634B40

01634B41

01634B42

01634B43

01634B44

n

e

k

o


が表示された時点で


アドレス番号

01634B40

01634B41

01634B42

01634B43

01634B44

の付いたメモリを確保しておく必要はないのだけど


free関数を使ってメモリ解放を行わなければ


アドレス番号

01634B40

01634B41

01634B42

01634B43

01634B44

の付いたメモリは


プログラムの実行が終了するまで


確保され続けることになります。


つまり

コンピュータは


プログラムの実行が終了するまで


アドレス番号

01634B40

01634B41

01634B42

01634B43

01634B44

の付いたメモリを


利用できないことになるんだ。


このように


もう使用しないのに


メモリを確保したままにしておくと


5バイト分のメモリなら影響はないのですが


積み重なって


何百バイト、何ギガバイトになってくると


コンピュータは利用できるメモリが少なくなり


プログラムの実行速度が遅くなったり


場合によっては


プログラムを実行できなくなります。


そこで


malloc関数を使って


メモリを確保した後


必要がなければ


free関数を使ってメモリの解放を


行うというわけです。」


アレサ「とっても優れたシステムなんですの(´▽`*)」


ソーラー「free関数を使ってメモリの解放すると


プログラムの実行速度を下げないようにできるんだね。


いろんなソフトで使われてそうだね。」







  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます