VBA object destruction - memory error

前端 未结 2 802
小蘑菇
小蘑菇 2021-02-10 12:59

I have an class object that I create, with references to other classes (none of the other classes reference each other). I am having a memory issue that gives the \'out of memo

相关标签:
2条回答
  • 2021-02-10 13:11

    It's tricky when you have references going both ways. Your terminate event never fires because the reference count isn't zero when you set your object to Nothing. So you can't clean up your references in the terminate event.

    One options is to create your own terminate method.

    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
    

    Now when you step through the code your Class_Terminate event will fire because the Terminate method took the reference count down to zero and VBA knew it would be able to clean up the object.

    The method I use is to store the memory location of the parent in the child and as a Long (or LongPtr in 64 bit). Read this post and especially Rob Bruce's comment in the comments section.

    ' 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
    
    0 讨论(0)
  • 2021-02-10 13:20

    Try using End keyword

    Sub Test1()
    
    Dim zwell As aclsWell
    
    For i = 1 To 2000
    Set zwell = New aclsWell
    Set zWell = Nothing
    
    Next i
    End
    End sub
    
    0 讨论(0)
提交回复
热议问题