この記事には複数の問題があります。改善
やノートページでの議論にご協力ください。コールスタックまたは呼び出しスタック(英: call stack)とは、プログラムで実行中のサブルーチン(関数)に関する情報を格納するスタックである。実行中のサブルーチンとは、呼び出されたもののまだ処理が完了していないサブルーチンのことを指す。実行スタック (execution stack)、制御スタック (control stack)、関数スタック (function stack) などとも呼ばれる。なお文脈によっては、短縮して単にスタックともいう。 コールスタックを使う目的はいくつかあるが、主たる目的はサブルーチンの処理を完了して制御を戻す(呼び出し側に戻る)ときに、どこに戻ればよいかを記憶しておくことである。 コールスタックはスタックとして構成されているので、呼び出し側はリターンアドレスをスタックに push し、呼び出されたサブルーチンが完了したときにリターンアドレスをコールスタックから pop する(そしてそのアドレスに制御を戻す)。呼び出されたサブルーチンがさらに別のサブルーチンを呼び出す場合も、リターンアドレスをコールスタックに push し、プログラムに書かれている通りに情報をスタックに積んだり下ろしたりする。あるサブルーチンに関する情報をコールスタックに載せることをワインド (巻き上げ, winding)、逆にそれを削除することをアンワインド (巻き戻し, unwinding) と呼ぶ。また、サブルーチンの呼び出しごとにコールスタックに格納するひとまとまりの情報の集合をスタックフレーム (stack frame) または単にフレームと呼ぶ[1]。 なお、コールスタックに割り当てられている領域を使い切ると「スタックオーバーフロー」と呼ばれる実行時エラーが発生する。スタックオーバーフローが発生したときの動作はプログラミング言語や実行環境によって異なるが、通例プログラムの異常終了といった未定義動作を引き起こし、回復不可能であることが多い。 1つの実行中のプログラム(より正確に言えばスレッド)には、1つのコールスタックが対応して存在する。シグナル処理や協調的マルチタスク処理で追加のスタックを使う場合もあるが、通常使用中のコールスタックは常に1つなので、これを単に「(そのタスクの)スタック」と呼ぶことがある。 低水準言語(アセンブリ言語)の多くでは、プログラマが明示的にスタックを操作する必要がある。一方、高水準言語からはコールスタックは透過的である。つまりコールスタックの存在を意識することなく、呼び出し階層構造によって実現される上位概念としてのプログラムロジックにのみ集中できるということである。コールスタックの詳細はプログラマからは見えず、引数あるいはローカル変数といった形でスタックから切り出された部分領域だけにアクセス可能で、スタックを構成しているメモリ全体にアクセスすることはできない。識別子を使ったサブルーチン(関数)の呼び出しは言語処理系によって対応するアドレスへのジャンプ命令に解決され、またスタックへのリターンアドレスの格納やリターンアドレスへの復帰といった下位レベルの前処理・後処理も隠蔽される。x86のcallとretのように、アセンブラレベルでもそのような下位レベルのスタック操作を隠蔽する命令が用意されているアーキテクチャもある。 各プログラミング言語におけるスタックの詳細は、コンパイラ、オペレーティングシステム (OS)、命令セットなどに依存する。x64のように、特定の条件を満たす関数引数に関しては、スタックを使わずレジスタを使って渡すアーキテクチャもある[2]。 いずれにせよ、言語環境を問わず、ソフトウェアを正常動作させるにはコールスタックを正しく保つことは重要である。コールスタックの容量は、デスクトップOS環境であっても既定で(スレッドごとに)数MiB程度しかなく[3][4]、組み込み環境ではさらに制限が厳しい。高水準言語では普段コールスタックの存在を意識しないで済むがゆえに、ヒープではなくスタック上に巨大な配列を確保して容量を使い切ってしまい、スタックオーバーフローを発生させてしまうといった初歩的な間違いを犯すこともある。 コールスタックが関係する具体例として、次の擬似コードを挙げる。subroutine DrawSquare(Point p1, Point p2, Point p3, Point p4){ ... 略 ... DrawLine(p1, p2); DrawLine(p2, p3); DrawLine(p3, p4); DrawLine(p4, p1); ... 略 ...} 上の疑似高水準言語のコードでは、サブルーチンDrawSquare内の4ヶ所から、直線を描画するサブルーチンDrawLineを呼び出すとしたとき、DrawLineは4ヶ所のうちのどこに戻ればよいかを知る必要がある。一般にDrawSquareのコード内でDrawLineを呼び出しているそれぞれの箇所で、呼び出し処理の次の命令のアドレス(これをリターンアドレスと呼ぶ)をコールスタックに格納することでこれを実現する。
概要
具体例
コールスタックの機能
Size:26 KB
出典: フリー百科事典『ウィキペディア(Wikipedia)』
担当:undef