スタックオーバーフロー
From Wikipedia, the free encyclopedia
スタックオーバーフロー (英: stack overflow) は、コンピュータプログラムにおいて、コールスタック領域の限界を超えたデータプッシュにより発生する、バッファオーバーフローの一種である。スタックバッファオーバーフロー (英: stack buffer overflow) とは別の概念である。
一般的なプログラムの実行環境では、サブルーチン(関数、プロシージャ、あるいはメソッドとも)の呼び出しに関する情報を格納するためのスタックメモリ領域(コールスタック)が確保される。サブルーチン呼び出しのたびにデータがスタックに積まれ(プッシュ)、サブルーチンが終わって制御フローが呼び出し元に戻るとスタックからデータが降ろされる(ポップ)。また、コールスタックはサブルーチン内でのみ使用されるローカル変数を確保するための領域でもある。オペレーティングシステム (OS) や実行オプションにもよるが、コールスタックに格納できる情報量には上限がある。コールスタックに蓄積されるデータ量が限界を超えるとスタックは「オーバーフロー」し、未定義動作を引き起こす。OSにもよるが、プログラム側で対策をとっていなければ通常はプロセスがクラッシュしてしまう。ただし、スタックオーバーフローの原因となりうるコードパターンは比較的限定されている。
スタックオーバーフローの発生原因のうち、最も多いのはサブルーチンの再帰呼び出しによる無限ループ(無限再帰)である。また、ソースコードの設計上は無限再帰ではなく、終了条件を決めて有限回数で打ち切るような有限再帰になっていたとしても、再帰呼び出しの階層数が深すぎると実行環境におけるコールスタックの上限を超えてしまい、スタックオーバーフローとなってしまう場合もある。ただし、末尾最適化を実装したプログラミング言語では、末尾再帰の形で書かれたサブルーチンをループへ展開することができ、スタックオーバーフローは起こらなくなる。フラットなループ処理に変換されることで、再帰呼び出しによりスタックを消費することが無くなるからである。なお、再帰ではないサブルーチン呼び出しであっても、呼び出し階層数が深すぎる場合には、やはりスタックオーバーフローが起こりうる。
次によくある原因としては、スタック上に巨大な配列を確保しようとすることである。コールスタックに格納できる情報量には上限があるため、巨大なサイズのローカル変数を定義するのではなく、ヒープ領域などを明示的に利用すべきである。配列1つのサイズがそれほど大きくなくても、再帰呼び出しなどでサブルーチンの呼び出し階層が深くなることによってコールスタックを食いつぶし、スタックオーバーフローを引き起こすこともある。