スタックのサイズには制限があります。一部の Windows システムでは 1 MB です。プログラムでスタック サイズを変更できますが、多くの場合、それは悪い考えです。
各スレッドに異なるスタックがあります。スタック変数は、スコープの最後で常に解放されます。例えば
void MyFunction
{ // begin of scope 1
std::string mouse("feep");
for (int i = 0; i < 10000000; i++)
{ // begin of scope 2
int x = 1; // x is on the stack
std::string cow("moo"); // cow is on stack
// end of scope 2, cow is destroyed then the stack is freed for cow and x before the next iteration of the loop begins
}
return; // end of scope 1, mouse is destroyed ant the stack is freed for mouse
}
上記のコードのスタックには、最大mouse
で 、i
、x
、およびが常に存在cow
します。再帰を使用すると、オーバーフローする非常に深いスタックになる可能性があります。例えば
void StackOverflowIncoming()
{ // begin of scope
int aVariableOnTheStack = 0;
StackOverflowIncoming();
// end of scope
}
上記の関数は、新しいスコープを永久に開き、スコープを離れることはないため、ある時点でオーバーフローします。
スタックをオーバーフローさせるもう 1 つの方法は、スタックalloca
を直接割り当てる (スタックが割り当てられたスコープが閉じられるとすぐに解放される) です。alloca
最大スタック サイズが 1 MB の場合、単純にスタックに 10 MB を割り当てるために使用します。スタックに巨大な構造体を割り当てることによっても実現できます。
void InstantStackOverflow()
{
char buffer[1<<24];
}
スタックへの割り当てが多すぎるという詳細な例については、この質問を参照してください。
スタックをオーバーフローさせる最後の最も独創的な方法は、プログラムの状態を破壊することです。これにより、プログラムはひどく混乱し、スタックのクリーンアップに失敗します。通常、次のように、未定義の動作をもたらす言語機能を使用してこれを行います。
void TryToCorruptTheStack()
{ // begin of scope
char buffer[1];
for (int i = -20; i < 20; i++)
buffer[i] = 5;
// end of scope
}
スタック破損のより詳細な例については、この質問を参照してください。