如果将一个对象数组声明为变量类型(以便使用IsEmpty函数轻松检查它是否已初始化),那么如果随后定义的数组元素被引用作为With语句的对象表达式(例如:With VariantObjArray(i)...),那么该对象变量数组元素将被错误释放(尽管With语句对对象变量的隐式复制在单个执行Through With语句范围的执行过程中功能正确)。
此外,数组元素对象变量的错误释放可能是内存泄漏,因为它发生在执行With表达式的同时,而不是作为任何标准的释放机制(如退出With语句或从子例程返回或显式设置为Nothing)的结果。
Sub DemoVariantObjArrayBug()
Dim i As Integer
Dim NextWkSh As Worksheet
Static VariantObjArray As Variant
If IsEmpty(VariantObjArray) Then 'Check to avoid unnecessary re-allocation of static or global array variable
ReDim VariantObjArray(1 To ThisWorkbook.Worksheets.Count)
For Each NextWkSh In ThisWorkbook.Worksheets
i = i + 1: Set VariantObjArray(i) = ThisWorkbook.Worksheets(i)
Next NextWkSh
End If
Stop 'and, to observe the bug, open the Locals window, expand its view of VariantObjArray, single step through
'the following code and observe each VariantObjArray element being deallocated with each cycle's execution
'of the "With" statement:
For i = LBound(VariantObjArray) To UBound(VariantObjArray)
With VariantObjArray(i) 'The bug workaround is to, instead of this, do something like the following...
' Dim SomeWkSh As Object: Set SomeWkSh = VariantObjArray(i)
' With SomeWkSh
Debug.Print """" & .Name & """: CodeName = " & .CodeName & ", Index = " & .Index
End With
Next i
End Sub
一种解决方法是明确使用中间对象变量,如上面的替代代码所示(最初被注释掉)。
- 我无法找到有关此错误的任何网络讨论,那么这真的是一个没有人遇到过的错误吗?
- 还是一个新的错误,最近引入,包括我的当前版本的Excel,Microsoft 365 MSO(16.0.14326.21052)64位?
- 它只发生在64位Office中吗?
- 这实际上是分配的对象内存泄漏还是仅仅是对象指针丢失?
static
或数组来保存对象。ReDim VariantObjArray(1到3)
,为每个元素设置一个数字,在with
中触摸一个元素而没有任何内容,它将变为空值而不是数字。 https://pastebin.com/0SJFELZk - GSergByVal
传递参数)- 我非常确定这可以解决问题(现在无法测试)。 - Mathieu Guindon