我创建了一个类对象,引用了其他类(其他类都没有引用)。我有一个内存问题,导致内存不足'循环并创建类的实例时出错。类和子例程的简化代码片段如下:
Class aclsWell
Option Explicit
Option Compare Text
Option Base 1
Private zclsSettings As bclsSettings
Private zclsInfo As bclsInfo
Private zclsProduction As bclsProduction
Private Sub Class_Initialize()
Set zclsSettings = New bclsSettings: Set zclsSettings.Parent = Me
Set zclsInfo = New bclsInfo: Set zclsInfo.Parent = Me
Set zclsProduction = New bclsProduction: Set zclsProduction.Parent = Me
End Sub
Private Sub Class_Terminate()
Set zclsSettings.Parent = Nothing: Set zclsSettings = Nothing
Set zclsInfo.Parent = Nothing: Set zclsInfo = Nothing
Set zclsProduction.Parent = Nothing: Set zclsProduction = Nothing
End Sub
模块:
Sub Test1()
Dim zwell As aclsWell
For i = 1 To 2000
Set zwell = New aclsWell
Set zWell = Nothing
Next i
End sub
完成Test1后,excel正在使用大约1 GB的数据,如果再次运行,我会收到错误消息。但是,如果我按下VBA窗口中的停止按钮,内存将清除。有没有办法模仿使用VBA命中停止按钮(如Application.stopmacro或类似的东西)。或者我在关闭对象的方式中有一个基本问题?非常感谢任何见解。
答案 0 :(得分:4)
当你有双向参考时,这很棘手。您的终止事件永远不会触发,因为当您将对象设置为Nothing时,引用计数不为零。因此,您无法在终止事件中清理您的引用。
一种选择是创建自己的终止方法。
Public Sub Terminate()
Set zclsSettings.Parent = Nothing: Set zclsSettings = Nothing
Set zclsInfo.Parent = Nothing: Set zclsInfo = Nothing
Set zclsProduction.Parent = Nothing: Set zclsProduction = Nothing
End Sub
Sub Test1()
Dim zwell As aclsWell
Dim i As Long
For i = 1 To 2000
Set zwell = New aclsWell
zwell.Terminate
Set zwell = Nothing
Next i
End Sub
现在当你单步执行代码时,你的Class_Terminate事件将会触发,因为Terminate方法将引用计数降为零,VBA知道它可以清理对象。
我使用的方法是将父节点的内存位置存储在子节点中,并存储为Long(或64位的LongPtr)。 Read this post,尤其是Rob Bruce在评论部分的评论。
' In your child class
Private m_lngParentPtr As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(dest As Any, Source As Any, ByVal bytes As Long)
' The Parent property
Public Property Get Parent() As Class1
Set Parent = ObjFromPtr(m_lngParentPtr)
End Property
Public Property Set Parent(obj As Class1)
m_lngParentPtr = ObjPtr(obj)
End Property
'Returns an object given its pointer.
'This function reverses the effect of the ObjPtr function.
Private Function ObjFromPtr(ByVal pObj As Long) As Object
Dim obj As Object
' force the value of the pointer into the temporary object variable
CopyMemory obj, pObj, 4
' assign to the result (this increments the ref counter)
Set ObjFromPtr = obj
' manually destroy the temporary object variable
' (if you omit this step you’ll get a GPF!)
CopyMemory obj, 0&, 4
End Function
答案 1 :(得分:2)
尝试使用End
关键字
Sub Test1()
Dim zwell As aclsWell
For i = 1 To 2000
Set zwell = New aclsWell
Set zWell = Nothing
Next i
End
End sub