関数呼出しとスタック


関数呼び出し関係というのはスタックに例えられることが多いです。 一番底に main 関数が実行されていて、そこから呼び出された関数が、 その上で実行されていて、 その上にさらに呼び出された関数があるという具合です。 で、 呼び出された関数の実行が終われば、スタックを戻して、 呼び出した側の続きを行うというわけです。

ちなみに、gdb ではこういった関数の呼出し関係を簡単に表示させることができます。
Cygwin 版を使っている人は、スタックのアイコンを触ってみましょう(詳細)。 Emacs + gdb なら、コマンドラインから where といれましょう(詳細)。 必ず、表示させてみること

で、局所変数は関数呼出し毎に作られて、 呼び出しの中だけで触れるものです。 というわけで、先ほどの図の 各要素(フレーム)のなかにローカル変数があると思うと分かりがいいです。

というわけで局所変数は、 関数が呼び出されるたびにあらたに作られ、関数呼出しが終わると消えてしまうものです。 言語を実装する場合も、このようなスタックが利用されています。 実際のコンパイラでは、フレームには局所変数用の領域に加えて、 Program Counter, 呼出し関数のフレームポインタやレジスタ待避領域などが加わり、 レジスタも活用されますが。

一方で、大域変数は、プログラム開始時からずっと一つだけ存在しているものだと 思ってください。 実装上も、プログラム文面などと同じく、固定領域が割当てられています。

実は、多くの実装では、局所変数アクセスの方が、大域変数へのアクセスより高速です。 加えて、局所変数は関数の中だけ見ていればいいので、バグの可能性も少ないです。 というわけで、共有する必要がないデータは、局所変数として作りましょう。


2001.11.04/ Tomio KAMADA: kamada@cs.kobe-u.ac.jp