Skip to content
Latchkey

Stack とは?関数呼び出しのためのメモリ

stack は、関数が呼び出されて return するにつれて伸び縮みするメモリ領域で、ローカル変数と管理情報を last-in, first-out の順序で格納します。

プログラムが関数を呼び出すたびに、その呼び出しのローカル変数、引数、そしてどこへ return するかを保持する「stack frame」を push します。関数が return すると、その frame は pop されます。この last-in, first-out の規律が stack を非常に高速にしますが、同時にサイズが固定でもあり、それが深い、あるいは暴走した再帰がオーバーフローを起こしうる理由です。

call stack の仕組み

関数呼び出しは frame を push し、return がそれを pop します。frame はローカル変数、パラメータ、return アドレスを保持します。確保はポインタを動かすだけなので、stack の操作はほぼ無料で、heap の確保よりはるかに安価です。

stack と heap

stack は寿命が短く関数スコープのデータを厳密な順序で格納し、return 時に自動的にクリーンアップされます。heap は寿命が長く動的なサイズのデータを格納し、手動または garbage collector によって管理されます。ほとんどのプログラムは両方を常に使います。

stack に何が乗るか

  • 現在実行中の関数のローカル変数。
  • 値渡しされた関数の引数。
  • 呼び出し後に実行を再開できるようにする return アドレス。
  • 保存されたレジスタと小さな管理情報。

なぜ stack は制限されるのか

stack は OS または runtime が定めた固定の最大サイズを持ちます。各呼び出しがその一部を消費し、frame は return 時にのみ解放されます。無制限の再帰は上限に達するまで frame を push し続け、stack overflow を引き起こします。

簡単な例

基底ケースなしに自分自身を呼ぶ関数は、呼び出しごとに新しい frame を push し、決して return しないため、stack はオーバーフローするまで増え、プログラムは stack overflow エラーで crash します。

CI における stack

stack overflow は通常ロジックのバグ(まずい再帰)を指すため、決定的であり retry しても役に立ちません。CI はそれらが最初に現れる場所であることが多いです。Latchkey のようなマネージドプラットフォームは、決定的な crash と一時的なインフラの失敗を区別し、後者だけを retry するため、本物のバグはきちんと表面化します。

重要なポイント

  • stack は関数呼び出しとローカルを last-in, first-out の順序で格納し、とても高速です。
  • サイズが固定なので、深いまたは無限の再帰はそれをオーバーフローさせます。
  • stack overflow は決定的なロジックのバグであり、retry すべき一時的な失敗ではありません。

関連ガイド