質問: 0 if bool sum += pattern3(g-1, b, false) sum += pattern3(g, b-1, true) else sum += pattern3(g, b-1, true) end return sum end #適当に値を入れて実行 p pattern3(14,16,true) #stack level too deep (SystemStackError) ``` こちらの場合は、いわゆるスタックに情報をためすぎた、つまり変数が多すぎたから起きたものになるのでしょうか? よろしくお願いいたします
回答: ローカル変数は通常スタックと呼ばれる領域に格納されます。 グローバル変数は通常ヒープと呼ばれる領域に格納されます。 これらは原則であって絶対ではありません。コンパイラの判断で変わることもあります。 いずれにせよ、プログラムで使えるメモリには二種類あります。 それを踏まえて、再帰を呼び出すと、呼び出された関数で再度ローカル変数の領域がスタックに再確保されます。そして、これ以上確保できなくなった時、スタックオーバーフローというエラーになります。 つまり、スタックオーバーフローになるかならないかは、 1. スタックがどの程度の大きさを持っているか(コンパイラオプションなどで指定できることもあります) 2. ローカル変数にどの程度のメモリが必要なのか(変数の型、宣言する数、コンパイラによる最適化などによって変わります) 3. 再帰の回数 の二つで主に決まります。 通常の関数呼び出しの場合、関数が終了した時点でスタックに積まれたローカル変数の領域は解放されますが、再帰の場合、呼び出し側の変数は呼び出された側が終了するまで解放されません。 このため、スタックオーバーフローが起きやすくなります。 ### 追記分 ``` return 0 if g > 1 && b == 0 return 1 if g == 0 ``` この部分が問題ですね。 g == 1 && b == 0 の時、次の条件に移りますが、ここで bool が true だと、b < 0 となって永遠に再帰が終わりません。 スタックオーバーフローが出るときには、変数が多すぎるとかなんとかいうより以前に、ほぼ無限ループが原因です。 無限にループしていないかどうか、関数内で変数の内容やループ回数をダンプしながらデバッグされたらいいと思います。