ショートカット
ファシリテーター × あり方
コーディングの向こう側
Hello, ANOTHER world!
オブジェクト指向のはなし
プログラミングのはなし
C言語実力診断クイズ
eSkillBooks
Hello, ANOTHER world!

ヒープメモリ

パラメータがスタック領域に格納されることはすでに解説しました。実は、パラメータだけでなく、関数の中で使用される変数は基本的にスタックに置かれます。ただしスタックに置かれたデータは関数の実行が終了して呼び出しもとに戻るときに消去されます(自動的に消えるので「auto 変数」とも言います)。そこで、関数を抜けても消えないデータを格納するには、スタックとは別の仕組みが必要です。そのために用意されているメモリ領域のことを「ヒープ領域」と呼びます(「ヒープメモリ」「ヒープエリア」などと呼ぶこともありますが、同じ意味です)。
ヒープ領域の操作は、C言語では malloc と free を使います(使ったことがあると思いますが)。C++ では new と delete を使います。
int *pi = (int *)malloc( sizeof(int) * 100 );
if ( pi != 0 ) {
    ...
    free( pi );
}
このようにヒープ領域からデータの格納先を確保することを「動的確保」と呼びます。
もうひとつ、ヒープを使う目的があります。それは、大きなメモリ領域を確保することです。スタック領域の大きさは限られていて、しかもあまり大きくありません。そこで、大きいメモリ領域が必要な場合はヒープから取り出すのが安全です。
では、スタックとヒープの違いを把握しましょう。スタックに確保される変数は関数の内部でのみ有効であり、関数から抜けるときに消去されます。なので、スタック変数は個々の関数の内側にあると思えば良いでしょう(本当は別の関数内の変数が共通のスタック領域に確保されるのですが、概念的には関数の内側に存在します)。それに対してヒープに確保された領域は関数の外側にあります。関数から抜けたときにも自動的には解放されません。また、ヒープから取ったひとつのメモリ領域を複数の関数から参照することもできます。
この図は概念的な構造を表しただけで、実際にはもう少し複雑です。
ヒープに確保する領域は int などの型をもっているわけではありません。実際には領域の開始アドレスとサイズによって管理されます。どんな型のデータとして使うかはプログラマの自由です。それで上のサンプルプログラムのようにキャストが必要になります。
補足:
厳密に言うと、(C++ を使わず)C言語だけ使うのならキャストは必要ではありません。が、キャストを使う方が良い理由があります。
スタックの場合は関数の終了と同時に変数が消去されますが、実はこれはコンパイラがそのような動きを関数に組み込んでくれているためです。変数がどこで生成されてどこで消滅するか(これを変数の「生存期間」などといいます)が明らかなので、コンパイラが自動的に制御することができます。しかしヒープの場合は生存期間をプログラマが自力で決定するので、コンパイラは生成と消滅のタイミングには関与しません。
このような自由さがある半面、動的確保はメモリ関連のバグの原因になることが多いのですが、それはどうしても避けて通れない部分です。少しでも間違いを減らす工夫をしながらプログラミングをしなければなりません(その一例)。
さて、次回はヒープについてもう少し詳しく解説することにしましょう。

("Hello, ANOTHER world!" は2001年11月から2002年11月にかけて作成されたコンテンツです。)