動的メモリ管理
次のプログラムは,動的に (実行時に) サイズを指定してメモリ領域を用意するプログラムの例です。
実行時まで長さがわからない配列を扱う際などに,このような手法を使うことになります。
#include <stdio.h>
#include <stdlib.h> /* malloc, free 関数のため */
int main(void)
{
int size = 5;
int *arr;
arr = (int *) malloc(size * sizeof(int)); /* メモリを動的に確保 */
/* メモリ領域を使用... */
free(arr); /* メモリを解放 */
return 0;
}
malloc 関数
動的に (実行時に) メモリ領域を確保するには,関数 malloc (memory allocate) を使います。
引数は確保すべきバイト数,返り値は確保されたメモリ領域へのポインタです (失敗時 NULL)。
arr = (int *) malloc(size * sizeof(int)) は,宣言 int arr[size] におおよそ相当します。
malloc 関数の返却型が void * (汎用ポインタ) なので,具体的なポインタ型にキャストするのがベターです (型チェックの厳しい C++ ではキャストがないとエラーが出ます)。
void *malloc(size_t size);
free 関数
malloc 関数で動的に確保したメモリ領域は,必ず free 関数で解放します。
void free(void *ptr);
解放されないメモリ領域は,ゾンビのように生き続け,メモリを占有し続けます。
長時間プログラムを走らせていると,些細なメモリ領域の解放し忘れが無数に重なり,やがてメモリを食いつぶします。
このようなメモリの解放漏れのことをメモリリーク (memory leak) と呼びます.
malloc 関数のバリアント
動的にメモリを確保するために使える関数には,malloc 以外にもいくつかの種類があります。
関数名 | 関数プロトタイプ | 説明 | ゼロクリア |
---|---|---|---|
malloc | void *malloc(size_t size); | 指定したバイト数 (size バイト) の領域を確保します。 | されない |
calloc | void *calloc(size_t n, size_t size); | 指定したバイト数 (n * size バイト) の領域を確保します。 | される |
realloc | void *realloc(void *ptr, size_t size); | 確保済みの領域を指定したバイト数で再確保します。 | されない |
calloc 関数は,malloc 関数と同様に指定したバイト数の領域を動的に確保する関数です。
働きは malloc 関数とほぼ同じですが,確保された領域がゼロクリアされる (0 で初期化される) 点が違います。
realloc 関数は,malloc/calloc/realloc 関数で確保済みの領域を指定したバイト数で確保し直します。
第 1 引数には,確保済みメモリ領域へのポインタを指定します。