ログイン
kid's world

メモリ領域の確保と開放

メモリ領域の確保と開放

はて,今回のテーマは何だったか……そうそう,「もっとたくさん記憶したい!」であった。変数をどんどんと宣言していけば,たしかにたくさんのデータを記憶できるのだが,それはエレガントなやり方ではない。実は「ポインタ」をうまく使えば,同じ型の大量のデータをたくさん記憶することができるのだ。

基本的なアイデアは,「たくさんのメモリを確保する!」ということ。たくさんのメモリを自分専用に確保して,あとはポイタを読み書きすればよい。前に説明したように「確保されたメモリ」でなければならない。使っていなさそうなメモリ領域を決め打ちして……なんてことは絶対にしてはならない。

そこでここからは,自分専用にメモリを確保する方法について説明しよう。

はじめに結論からいうと,メモリの確保はmalloc関数,メモリの解放はfree関数によって行う。しかしこれらの関数は,このままでは使えない。以前,printf関数を使うために「stdio.h」をインクルードしたように,これらの関数を使うときは「stdlib.h」をインクルードしなければならない。つまり,プログラムの先頭に,

#include <stdlib.h>

を追加する。最初は,変数1つぶんのメモリ領域を確保するところから始めよう。

malloc関数

malloc関数は,指定された引数に指定されたバイト数ぶんのメモリ領域を確保し,その先頭アドレスを返してくれる。たとえば10バイトのメモリを確保するには,

malloc(10);

と書く。しかし,これではメモリを確保しただけで,アドレスを受け取れていないので,たとえばint型を指すポインタ変数pを宣言して,次のように書く。

int *p;
p=malloc(10);

ところが,まだこれでは問題がいくつかある。まず,int型は10バイトも必要としない場合が多い。ほとんどのコンパイラではint型は2バイトか4バイトだ。任意の型のバイト数は,sizeof演算子で知ることができる。そこで,

int *p;
p=malloc(sizeof(int));

と書けば,int型にぴったりのサイズのメモリが確保でき,その先頭アドレスがpに代入される。

ほとんどの場合,これでめでたくメモリが確保できる。しかし,いつでもメモリが確保できるとは限らない。なぜならメモリは無尽蔵にあるわけではないからだ。ではメモリが確保できなかったときはどうなるのだろう。

そのときmalloc関数は「NULLポインタ」というものを返す。よって,NULLポインタがポインタ変数pに代入されたかどうかを調べて,もし代入されていたらそれ以上のプログラムの実行は無理だと判断し,プログラムを終了するなどの措置をとればよい。それは,具体的には次の1文で処理できる。

if(p==NULL) exit(1);

イコール「=」が2つ連続しているので注意。「if」や「exit」についてはあとで解説する。今はこの1文で「メモリが確保できなかったときにプログラムを終了できる」ということだけわかれば十分である。

free関数

malloc関数によって確保されたメモリ領域が不要になったら,それをすみやかに解放してほかのプログラムなどが利用できるようにしなければならない。いつまでも確保し続けているのは,メモリのムダ遣い以外の何ものでもない。

メモリを解放するには,free関数を使う。この関数の使い方は簡単である。malloc関数で確保したメモリの先頭アドレスを引数に渡すだけである。

free(p);

この1文で,確保したメモリは解放される。

ではここで例を示そう。List 5は,int型変数1つぶんのメモリを確保して,簡単な計算を行い,メモリを解放する例である。ついでにポインタ変数pのアドレスと内容も表示している。

List 5: メモリを確保する例

#include <stdio.h>
#include <stdlib.h>

main()
{
  int *p;
  p=malloc(sizeof(int));
  if(p==NULL) exit(1);
  
  *p=24*60;
  printf("*p: %d\n",*p);
  printf(" p: %p\n",p);
  printf("&p: %p\n",&p);
  
  free(p);
}

この例で使用している変数は,int型を指し示すポインタ変数pの1つだけである。それを宣言した直後は,ポインタ変数はあさっての方向を向いている。そこでmalloc関数を使い安全なメモリ領域を確保して,そこを指すようにしている。そして,

*p=24*60;

という文では,malloc関数によって確保されたメモリ領域に計算結果を保存している。結果を表示し,最後に忘れずにfree関数で確保したメモリ領域を解放する。

筆者のPCでは,Fig. 7のような実行結果となった。この結果から,Fig. 8のように,malloc関数によってアドレス1420からの2バイトが割り当てられていたことがわかる。

Fig. 7: List 5の実行結果

*p: 1440
 p: 1420
&p: 0F58

Fig. 8: malloc関数によって確保された領域

/c/pointer-fig8.png


たくさんの値を扱う」へ進む

広告


©Toshio Koide 1996-2007.

目次

リンクについて

リンクは御自由にどうぞ。

メール

mail.gif

広告