見出し画像

Facebookから【プログラムにおける動的メモリ確保の話】

こんにちは。昼下がり、二月ほど前に書いたFacebookからの転載で更新します。少しプログラミングに関する話題です。以下。


おはようございます。秋が少しずつ深まり、日の出の時間も遅くなりつつある朝です。ただいま午前6時。少しだけ書きます。今日は、プログラムにおける動的メモリ確保の話。

いわゆるコンパイラ言語(C言語など)では、変数は変数型を指定した上で使用する前に宣言するのが一般的です。特に、C言語では関数ブロックの中で宣言した変数は自動変数として主記憶上のスタック領域に確保され、その関数がリターンされた時点でスタックがホップされメモリーが解放される、という動作になります。配列も同様で、要素数(配列の長さ)を指定した上で連続したメモリー領域をスタック上に確保します。

ただし、プログラミングの必要上、例えば処理の途中で任意の長さの連続したメモリー領域が必要になった時などは、必要なメモリー領域を動的、つまり実行時に確保することがあります。この時、一般には標準ライブラリに含まれる「malloc」という関数を利用します。

mallocのプロトタイプは、ヘッダーに宣言されており、

void *malloc(size_t size)

となっています。size_tは、処理系により長さが異なりますが、主にunsignedの整数型をtypedefで定義したもののようです。

引数に、必要なメモリーの長さを指定します。一般に、バイト数で連続したメモリーを確保する場合は、char型のサイズ×必要な数、という書き方でメモリー領域を確保します。返り値はポインターで、確保されたメモリーの先頭アドレスが汎用ポインターのvoid型で返されます。通常は、このvoid型のアドレスを任意の変数型にキャスト(型変換)して利用することが一般的です(型変換しておいた方がアドレス演算でメモリーを操作するときに扱いやすい)。

調べると、厳密にはvoidをキャストせずに利用しても問題なく扱う方法もあるようですが、恐らく、今日のコンパイラではvoidのポインターをそのまま扱おうとした時点でコンパイル時のワーニング(警告)が出されるかと思います。

mallocで確保した領域は、主記憶のスタックではなくヒープに配置されます。配列は、扱いによってスタックオーバーフローの原因になりうることもありますが、一般に、ヒープオーバーフローはスタックオーバフローよりは発生しにくいと言えるかも知れません。

mallocで動的に確保したメモリーは、使用を終了した時点でプログラマーが明示的に解放(free)しなければなりません。そうしない場合、確保したメモリーが永続的に残ることになり、実行を継続すればするほど不必要なメモリー領域が増えていきます。これがいわゆるメモリーリークであり、ソフトウェアの内容によっては深刻な影響がある場合があります。他の言語では、こうした処理を処理系が処理する場合があり、それがいわゆるガベージコレクションですが、C言語由来の言語では一般にメモリーの管理はプログラマーに委ねられることになります。

特にC言語では、配列=ポインターと実質的には同等であるため、配列を宣言して利用する代わりに、mallocで連続したメモリー領域を動的に確保して配列として利用するといったシーンは多いかと思います。

今朝はここまでにしますが、APIによってはmallocがラッピングされている場合もあります。ただし、本質的には考え方は同じです。

また、興味があればお調べになってみてください。

いいなと思ったら応援しよう!