私は、スタックがオーバーフローすると、無限ループまたは停止条件のない再帰関数が停止するという噂を聞いたことがあります。そうですか?例えば無限ループと停止条件のない再帰関数はいつ終了するのですか?
:
void call()
{
call();
}
または
for(;;){;}
スタックがオーバーフローしたときに、彼らが本当に停止しますか?
更新:実際に停止すると、再帰呼び出しの回数を検出できますか?
私は、スタックがオーバーフローすると、無限ループまたは停止条件のない再帰関数が停止するという噂を聞いたことがあります。そうですか?例えば無限ループと停止条件のない再帰関数はいつ終了するのですか?
:
void call()
{
call();
}
または
for(;;){;}
スタックがオーバーフローしたときに、彼らが本当に停止しますか?
更新:実際に停止すると、再帰呼び出しの回数を検出できますか?
本当に言語の選択に依存します。
一部の言語では、システムまたは言語に依存する条件に基づいて、スタックオーバーフローを伴う無限再帰関数が停止します。これは、多くの関数呼び出しと戻りの実装では、関数呼び出しごとに新しい領域が割り当てられ、領域がなくなるとプログラムが失敗するためです。しかし、他の言語(Schemeやさまざまなgccの最適化レベル)では、実際にこのプログラムを永遠に実行することができます。なぜなら、呼び出しごとにスペースを再利用できることを認識するほどスマートなからです。
一部の言語では、無限ループは永遠に実行されます。あなたのプログラムは継続して実行され、決して進歩しません。他の言語では、無限ループはコンパイラによって最適化されます。例として、新しいC++ 0x標準では、コンパイラはループが終了するか、グローバルに可視のアクションをとることを想定することができます。したがって、コンパイラが無限ループを見ると、存在するので、ループは実際に終了します。
つまり、それは本当に依存しています。この質問には固くて速い答えはありません。
希望すると便利です。
最初の例は再帰的なメソッド呼び出しです - call
(ほとんどの言語と環境で)を呼び出すたびに新しいスタックフレームが作成され、最終的にスタックがなくなります(スタックオーバーフロー状態になります) 。
2番目の例では、再帰的なメソッド呼び出しは必要ありません。これは単なるループです。スタックフレームを作成する必要はなく、スタックはオーバーフローしません。
例を挙げてください - 最初の例では、考えるよりも速くスタックオーバーフローが発生します。 2つ目はあなたのファンを本当に速く回転させますが、それを殺すまで何も起こりません。
"アップデート:本当に停止した場合、再帰呼び出しの回数を検出できますか?「
あなたは最も確かにすることができます:
call(int n){
print(n)
call (n+1)
}
は、それからちょうど呼び出す:
call(1)
をスタックオーバーフローが発生した場合、最後に印刷数を見てこれは、メソッドの数は、あなたが持っていた呼び出しをされました。 。
希望はこのことができます!
NS
O k、それで、スタックフレームがいくつ流れたのかを検出する方法はありますか? – xsari3x
はい。あなたのコンピュータは、スタックの先頭へのポインタを保持し、スタックの最大アドレスを知っています。新しいスタックフレームを作成するように求められたら、スタックポインタの新しい値がその最大アドレスを超えていないことを確認します。 –
私の更新を確認することができます&事前にお礼を – xsari3x