Visual Studio 2010 でコンパイルしたプログラムでスタック オーバーフローが発生しました。スタック (8 KiB) に割り当てられた小さな char 配列を使用して、do-while ブロック内で文字列関連の作業を行うマクロがあります。次に、このマクロを同じスコープで何度も使用する関数があります。そして今、スタックオーバーフローが発生しています。
スタック割り当ては do-while ブロックに対してローカルであると想定していたため、ブロックが終了すると配列は存在しなくなり、関数の全体的なスタック使用量には寄与しなくなりますが、間違っていたようです。
デバッガーを使用すると、関数に入ると _chkstk() が呼び出されることがわかりました。この関数の引数として、その関数内のマクロの各呼び出しからの 8 KiB 配列すべての合計よりもわずかに大きいスタック サイズがあります (他のローカル変数のためにわずかに大きくなります)。
簡単な例を使用して問題を再現しました。
void func(void)
{
{char a[500000];}
{char b[500000];}
{char c[500000];}
{char d[500000];}
{char e[500000];}
}
単純なコンソール アプリケーションで main() からこの関数を呼び出すと、スタック オーバーフローが発生します。ただし、ブロック ステートメントを 1 つを除いてすべて削除しても問題なく実行されます。
これが意図したとおりに機能しているかどうか疑問に思っていますか?
関数に必要な合計スタック サイズはどのように計算されますか? 関数に必要なスタック サイズはどのように計算されますか? スタック上の配列は、範囲外になった後でも、関数の合計スタック サイズに影響しますか?
スタック オーバーフローが発生するのはなぜですか?