【すたっくおーばーふろー】

スタックオーバーフロー とは?

最終更新:
💡 呼び出しの積み重ねが、上限を超える

関数呼び出しの記録などに使うスタック領域を使い果たした状態です。終了しない再帰だけでなく、正常に終わる処理でも呼び出しが深すぎると起きます。エラーの名前や動作は言語・実行環境によって異なります。

📌 このページのポイント
呼び出しが、スタックの上限へ戻れる深さ呼び続ける空き領域⚠ 上限を超える関数B関数A開始点再帰呼び出し再帰呼び出し開始点再帰呼び出し終了条件があっても、深すぎれば発生✓ 繰り返す呼び出しと終了条件を確認
呼び出しの深さを示す模式図です。実際のメモリ配置や上限は実行環境によって異なります。
ひよこ ひよこ
コールスタックって何?
ペンギン先生 ペンギン先生
関数を呼び出したとき、呼び出し元へ戻るための情報などを積む領域だよ。呼び出し先が終わると、その情報を使って元の処理へ戻る。実行環境によって保存する内容は違うけれど、呼び出しを重ねすぎると、使える容量の上限に達してしまうんだ。
ひよこ ひよこ
再帰が無限に続くと起きるの?
ペンギン先生 ペンギン先生
自分を呼ぶ再帰が終わらない場合は、典型的な原因だね。でも終了条件があっても、そこまでの呼び出しが深すぎれば起きる。図の右側は、呼び出しが戻らないまま積み重なる例。単純なループを何度も回すことと、戻る前に関数を何重にも呼ぶことは違うんだ。
ひよこ ひよこ
パソコン全体のメモリがなくなったの?
ペンギン先生 ペンギン先生
必ずしもそうではないよ。スタックに使える容量は、パソコンのメモリ全体とは別に制限されることがある。JavaではStackOverflowError、JavaScriptではMaximum call stack size exceededなどが出る。上限やエラー時の動作は、言語・実行環境によって違うんだ。
ひよこ ひよこ
どうやって原因を調べる?
ペンギン先生 ペンギン先生
エラーのスタックトレースを見て、同じ関数や関数の組み合わせが繰り返されていないか調べよう。終了条件に到達できるか、呼び出しごとに条件へ近づいているかを確認する。プロパティのsetterが、自分自身へ代入してまた呼ばれるような、見えにくい再帰もあるよ。
ひよこ ひよこ
直すには上限を増やせばよい?
ペンギン先生 ペンギン先生
無限に呼び続けるバグなら、増やしてもいずれ使い果たすよ。終了条件を直す、深さを減らす、ループや別のデータ構造へ置き換えるなど、原因に合わせて考えよう。上限の調整は実行環境の条件を確かめて行う。同名のQ&Aサイト「Stack Overflow」と、プログラムのこのエラーは区別して読もう。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「スタックオーバーフロー」って出てきたら「関数呼び出しなどの積み重ねで、スタックの容量を使い果たす状態」と思えばだいたいOK!
📖 おまけ:英語の意味
「Stack Overflow」 = スタックの溢れ
💬 stackは積み重ね、overflowは溢れること。プログラムの呼び出し情報などを置く領域の上限を超える、という意味で使われるよ。

参考資料

← 用語集にもどる