「スタック領域が不足しています。」

ブログ

はじめに

 「スタック領域が不足しています。」というエラーは再帰呼び出しを行い階層が深くなってしまったような時に発生するエラーです。
 再帰呼び出しとは、自分自身を呼び出すような関数の事です。

 その他にWorksheet Changeなどのイベントプロシージャで変更のあったセル自体に編集を加えるなどの操作でも起こる可能性があります。
 ・Worksheet Changeが反応しなくなった時

エラーが起こるコードの例

 以下のプログラムは、再帰呼び出しの最も簡単な例です。
 macro()を実行すると「スタック領域が不足しています。」のエラーが発生します。

Sub ireko(n As Long)
    n = n + 1
    Debug.Print n
    ireko n
End Sub
Sub macro()
    ireko 1
End Sub

 このプログラムでは Debug.Print でカウントしているので、どのくらいのスタックが呼び出されているかがわかります。
 スタックは関数が展開されるメモリの大きさや自身のPCの能力により数は変化します。

スタックとは

 プログラムは関数を呼び出すと、メモリ上に展開され、計算を終えるとメモリから解放されます。
 1つの関数を実行して終了すれば、スタック数は1つです。
 もし、関数Aの中で関数Bを呼び出すと、スタック数は2つとなり、後から呼び出した関数Bが終了すると関数Aに戻ってきます。

 身近な例ですとExcelでメッセージボックスをモーダルで表示させたとき、OKボタンを押さないと他の処理は出来ません。これはメッセージボックス関数が終了していないためです。

 上のプログラムでは、ireko関数内部でirekoを呼んでいます。この手法を再帰呼び出しと言います。
 再帰呼び出しは決して間違った手法ではないのですが、今回のようなスタック領域不足を起こしやすい要因を孕んでいます。
 再帰呼び出しを使ったプログラムはスタック不足を起こす前に終了しなければなりません。

Sub ireko(n As Long)
    n = n + 1
    Debug.Print n
    
    If n > 1000 Then Exit Sub
    
    ireko n

End Sub

 上記のように n が 1000 を超えたら終了するにようにすればエラーを回避できます。

まとめ

 「スタック領域が不足しています。」というエラーは再帰呼び出しをしている可能性が高いのでデバッグで停止した場所(関数)を確認してみましょう。

 再帰呼び出しする関数を作る場合は、呼び出しの階層が深くならないうちに終了するような設計が必要です。
 
 再帰呼び出しでよく使われる例として、フォルダ内のファイル一覧をサブフォルダも含めて探すというプログラムがあります。
 このプログラムでは、フォルダ内のファイル数が多くてもそれほど問題にはなりませんが、サブフォルダの階層が深くなればなるほど再帰回数が増えてスタック領域が圧迫されることになります。ただしサブフォルダの階層の深さが数千ということはまずありえないので、エラーの心配はほとんどないと言えます。
 以下のサンプルがありますので、参考にしてみてください。

フォルダ内のファイル一覧

コメント

タイトルとURLをコピーしました