我有几个同事正在查看 Excel VBA 中的一些错误代码,想知道调用堆栈中的级别数是否有限制
6 回答
除非函数是尾递归的并且 VBA 可以处理(它不能),否则您将遇到堆栈溢出。
作为一个简单的测试,我将以下代码片段组合在一起:
Dim count As Integer
Sub Rec()
count = count + 1
Cells(1, 1) = count
Call Rec
End Sub
这告诉我们这个限制是 4007 次迭代,至少在我这里的 Excel 2007 版本中。
我知道的老问题,但我认为在我今天研究这个问题时获得一些关于这个问题的最新信息可能会很有用。
对于 Excel 2016 中的无参数过程,硬限制似乎是 6801 次调用深度。正如 VBA_interested 所说,这个数字随着递归过程的参数数量而减少。
我在 Excel 2016 中运行了以下测试:
Sub RecurseStatic(不带参数)在 6801 次递归后溢出。
Sub Recurse1(带 1 个参数)在 6442 次递归后溢出。
Sub Recurse2(带 2 个参数)在 6120 后溢出。
Option Explicit
Sub RecurseStatic()
Static i As Long
Debug.Print i
i = i + 1
RecurseStatic
End Sub
Sub RunRecurse1()
Recurse1 0
End Sub
Sub Recurse1(i As Long)
Debug.Print i
Recurse1 i + 1
End Sub
Sub RunRecurse2()
Recurse2 0, 0
End Sub
Sub Recurse2(i As Long, j As Long)
Debug.Print i, j
Recurse2 i + 1, j + 1
End Sub
简短的回答是肯定的,最终你会得到一个堆栈溢出异常。
虽然不确定限制是多少。
我刚刚在 Excel 2003 中运行了这个宏,并在收到错误 28“堆栈空间不足”之前进行了 4775 次调用:
Sub Macro1()
recurse (0)
End Sub
Sub recurse(level As Long)
ActiveCell.FormulaR1C1 = Str$(level)
Call recurse(level + 1)
End Sub
我在 Excel 2013 中运行了 Anders 的代码,结果只有 1180。不确定他们是否减少了较新版本的 Excel 中的递归限制,或者问题是否与机器有关或其他问题。
编辑:另外,更改:ActiveCell.FormulaR1C1 = Str$(level) 到 Range("A1").FormulaR1C1 = Str$(level)
呼叫次数降至 807。我还添加了 Option Explicit。
堆栈内存消耗。
据我了解,堆栈是否用于存储过程的参数以及过程中的局部变量。
因此,堆栈空间的消耗与递归调用的数量成正比。
所以所需的堆栈大小类似于:递归调用的数量*(调用参数的大小+局部变量的空间)