Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
malloc() / calloc() / realloc() / free()
プログラムの実行中に必要な分だけメモリを確保し、使い終わったら解放する仕組みです。配列のサイズを実行時に決めたいときや、大きなデータを扱うときに使用します。これらの関数は『<stdlib.h>』に含まれています。
構文
#include <stdlib.h> // size バイトのメモリを確保します(初期化しません)。 void *malloc(size_t size); // num 個の要素(各 size バイト)を確保して 0 で初期化します。 void *calloc(size_t num, size_t size); // 確保済みのメモリを new_size バイトに変更します。 void *realloc(void *ptr, size_t new_size); // 確保したメモリを解放します。 void free(void *ptr);
動的メモリ関数一覧
| 関数 | 概要 |
|---|---|
| malloc(size) | 指定バイト数のメモリをヒープから確保します。初期値は不定です。確保に失敗するとNULLを返します。 |
| calloc(num, size) | num個のsize バイト要素を確保し、全バイトをゼロで初期化します。整数配列の初期化に便利です。 |
| realloc(ptr, new_size) | ptrが指すメモリ領域のサイズをnew_sizeに変更します。必要なら新しい場所に移動し、元の内容をコピーします。 |
| free(ptr) | malloc/calloc/reallocで確保したメモリを解放します。NULLを渡しても安全です。解放済みのポインタを再解放してはいけません。 |
サンプルコード
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
// 実行時に要素数を決めて配列を確保します。
int n;
printf("要素数を入力してください: ");
scanf("%d", &n);
int *arr = malloc(sizeof(int) * n);
if (arr == NULL) {
fprintf(stderr, "メモリの確保に失敗しました。\n");
return 1;
}
// 値を設定して出力します。
for (int i = 0; i < n; i++) {
arr[i] = (i + 1) * 10;
}
for (int i = 0; i < n; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
// 使い終わったら必ず解放します。
free(arr);
arr = NULL; // ダングリングポインタを防ぐためNULLを代入します。
// calloc は 0 で初期化されます。
int *zeros = calloc(5, sizeof(int));
for (int i = 0; i < 5; i++) {
printf("%d ", zeros[i]); // すべて 0 が出力されます。
}
printf("\n");
free(zeros);
// realloc で動的に配列を拡張します。
int *buf = malloc(sizeof(int) * 3);
buf[0] = 1; buf[1] = 2; buf[2] = 3;
int *new_buf = realloc(buf, sizeof(int) * 6);
if (new_buf == NULL) {
free(buf);
return 1;
}
buf = new_buf;
buf[3] = 4; buf[4] = 5; buf[5] = 6;
for (int i = 0; i < 6; i++) {
printf("%d ", buf[i]); // 『1 2 3 4 5 6』と出力されます。
}
printf("\n");
free(buf);
return 0;
}
概要
動的に確保したメモリは「ヒープ」と呼ばれる領域に置かれます。スタック上の自動変数とは異なり、明示的に『free()』を呼ぶまで解放されません。確保したメモリを解放しない「メモリリーク」はプログラムの実行時間とともにメモリ使用量が増え続ける原因になります。必ず確保したメモリは解放してください。
また、解放済みのメモリを再度使用する「ダングリングポインタ」や、同じメモリを二重に解放する「二重解放」は深刻なバグを引き起こします。解放後は必ずポインタに『NULL』を代入してください。
『realloc()』は失敗したとき元のポインタを解放しないため、必ず別の変数でNULLチェックしてから代入してください。メモリに関連する関数の詳細は『sizeof』も合わせて参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。