2008.08.08
C言語では、メモリはどうやって確保されている?
勉強会は週に1回開催していて、メイン担当は持ち回り制である。
で、このブログ記事を更新するのはメイン担当者の役割だ。
と、ルールを決めた本人が自分の当番を忘れてしまっていて「やべっ、示しがつかない…」と猛反省。
さて、今回はC言語で「変数はメモリ内にどうやって格納されていくのか」のお話。
深いところまで突っ込んでいこうと思ったのだが、文章化すると思ったより長くなってしまったので序論な感じではある。
C言語では、関数内のローカル変数は、関数を抜けると確保していたメモリ領域は開放される。
この時に使われるのはメモリ内の「スタック」と呼ばれる領域だ。
スタックというのは後入れ先出し方式で使われ、その名の通り、後に格納した値から先に使う(解放する)時に利用される領域である。
int a = 123;
int b = 987;
という宣言をしたとしよう。
メモリの下(番地が大きい方)から値が格納されていくので、下図のようなイメージとなる。
├────────┤
│ 987 │
├────────┤
│ 123 │
├────────┤
│ < 使用済領域 > │
└────────┘
ローカル変数なので、関数を抜けると
├────────┤
│ │
├────────┤
│ │
├────────┤
│ < 使用済領域 > │
└────────┘
となって空いたところは再び使用可能となる。プログラムはこうやってメモリを活用しているのだ。
ところがこれでは問題が起きるときがある。
スタックの領域は、使用する領域サイズが明確なときはシンプルな構成で処理可能だが、動的に領域が確保される変数の扱いには不向きだ。
例えば、C言語には領域数を指定してメモリを動的に確保できる malloc という関数があるが、malloc で確保した領域は明示的に開放を指示(free)しない限り保持したままで使える。
malloc により確保された変数はスタックのように後入れ咲き出し方式ではないわけだ。
この場合は「ヒープ領域」という場所に確保される。
ヒープ領域はスタックと違って上から(番地の若い順から)確保されていく。
同じくイメージで書くと下のような感じだ。
┌────────┐
│ < 使用済領域 > │
├────────┤
│ 動的に確保 │
├────────┤
│ 動的に確保 │
├────────┤
スタックと違って確保された領域は開放命令によって空き状態に戻る。開放命令が呼ばれる順は確保した順とは無関係なので、穴がボコボコと空いていくイメージだ。
穴がいくつか集まってある程度の大きさになると再びその領域が使われるようになる。
これがヒープ領域である。
まとめると、ヒープは上から、スタックは下からメモリを使っていく。図にするとこんな感じだ。
ヒープ領域
┌────────┐
│ < 使用済領域 > │
├────────┤
↓
↑
├────────┤
│ < 使用済領域 > │
└────────┘
スタック領域
これ以外に、静的な変数に使われる領域もあり、例えばグローバル変数はスタックではなくこの静的変数用の領域に確保される。
以上が、C言語におけるメモリ確保のお話である。
C言語を完全理解するにはこうした「メモリ」の知識が必須になってくるのだが…
PHP や Python などのいわゆる Lightweight Language の本にはこうした「メモリ」についての話はほとんど出てこない。
C言語をマスターする大きな壁に「ポインタ」があり、このポインタを理解しようとするとメモリの話が出てきて挫折してしまう人が実に多い。
けど、知っていると言語の理解が深まるので、なんとな~くでも感じ取っておくと良いと思う。
次回は、Pythonではどうなんだ?という話をする予定。
Trackback URL
Comment & Trackback
Comment feed
Comment