Link to home
Start Free TrialLog in
Avatar of valhallatech
valhallatech

asked on

Class_Terminate not firing

Hi experts

I have a custom class module which I instatiate serverl hundred times in a loop as I iterate through a recordset. The problem I'm having is that access is running out of 'databases' or 'tables' as its whim takes it.

Someone suggested in another forum that this could be related custom objects not being released. I have one class, which has its properties serveral other objects (class modules instantiated).  I explicity release this object by setting it =nothing, but alarm bells are ringing now that I notice that it  doesn't execute the terminate method. Can anyone suggest what could be the possible causes of this?


Here's an illustration of what I'm talking about:

Class Fleas:
-----------------------
Public Property Get HowManyFleas()
    HowManyFleas = "lots and lots"
End Property


Private Sub Class_Initialize()
    Debug.Print " New set of fleas"
End Sub

Private Sub Class_Terminate()
    Debug.Print "No more fleas"
End Sub
------------------------------------------

Class Dog:
------------------------------------------
Dim MyFleas
Private Sub Class_Initialize()
    Debug.Print "A dog is born"
    Set MyFleas = New Fleas
   
End Sub

Function Eat()
    Debug.Print "ymym arghymm aslkjs"
End Function

Public Property Get Fleas()
    Set Fleas = MyFleas
End Property

Function Bark()
    Debug.Print "woof"
End Function


Private Sub Class_Terminate()
    Debug.Print " A dog dies"
    set MyFleas = nothing
End Sub
------------------------------------------

Here's a possible session from the immediate window and what is produced:
________________________________________________________________
set MyDog = new dog
A dog is born
 New set of fleas
debug.? MyDog.eat
arghymm aslkjs

debug.? MyDog.Bark
woof

debug.? MyDog.Fleas.HowManyFleas
lots and lots
Set MyDog=nothing
 A dog dies
No more fleas
-------------------------------------------------------------------------------------------

As you can see after setting MyDog = nothing the sub Class_Terminate()  for dog executed and similarly so did the Class_Terminate for fleas.
However this is not happening in my (much more elaborate) real world scenario and so I fear much gargabe isn't  being collected and access is eventually producing an error as a result.

Any ideas what it takes to stop Class_Terminate() executing?
I've made this urgent at 500 points because a) its damned tricky and no-ones had a crack at my original attempt to get this answered & b) I need it urgently
Glenn
SOLUTION
Avatar of harfang
harfang
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
hehe

In your excellent examples, add to the general section of Fleas:

   Public Master As Dogs

In Class_Initialize of Dogs, add:

   MyFleas.Master = Me

And run the debug window code again... (more fun with my zsfmsgOpen trick, though)
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of GreymanMSC
GreymanMSC

Damn...must...type...faster...

:)
Sorry Greyman :)

But the speech about adding a .Close method is excellent. This was in fact the solution I ended up with and I should have mentioned it here as well.
It's all good, harfang.  I do like that memory trace trick of yours.  Conjuring form instances is a rather inefficient way of tracing memory leaks, but exceedingly fun!
Avatar of valhallatech

ASKER

thx for both inputs - I won't get a chance to test the ideas for another 24 hrs or so :-(
I've suspected its the cross referencing as there is much pointing back to parents - I had a trivial attempt at addressing this and gave up as it didn't look like it would work so I abandoned it.

The forms as a 'mirror' of whats in memory is a neat idea - I'll play with that  - at the moment I just record a random key for each object in a table and note update the status of that on initalise and terminate - the form though will provide a reflection of what -is- in memory not what should be.

I think the close method is very sound and will have to become part of my standard coding practice I think.

The only concern I have with both observations is that the class_terminate method didn't even try to execute - I had debug.? and break points in there and the program flow just didn't even execute the method, like the terminate event never occured. I'm hoping the close method notion will make this  immaterial

THanks both for your input thus far - I've been pulling out what remaining hair I have over this
Glenn
> The only concern I have with both observations is that the class_terminate method didn't even try to execute

You seem to assume that

   Set MyDog = Nothing

is somhow equivalent to

   MyDog.Class_Terminate()

This is not the case. VB decides how and when to use the Class_Terminate handler for each object. To simplify things, imagine that each instance of a class has a hidden property called CountRefs.
When you use Set ObjectRef = New claAny, the object is created, Class_initialize is executed and CountRefs is set to 1.
When you use Set MyVar = ObjectRef, CountRefs is increased by one.
When you use Set MyVar = SomethingElse, CountRefs is decreased.
When you use Set MyVar = Nothing, likewise (if it referenced the object before)
When MyVar is removed (goes out of scope), likewise.
Whenever CountRefs drops to 0, Class_Terminate is executed and the memory is reclaimed...
If CountRefs never drops to 0 -- and if you no longer have access to the variable pointing to the object... Class_Terminate is never executed

It is  probably a little more complex than that, but everything *happens* as if it was!

Finally, do not assume that the .Close method will somehow trigger the Class_Terminate event. The .Close method will simply make sure that you set all object variables to Nothing, which will at some point drop the referenced objet's "CountRefs" to 0 and allow VB to close *those*

Cheers!
>You seem to assume that
>Set MyDog = Nothing
>is somhow equivalent to
>   MyDog.Class_Terminate()

I didn't assume they were synonmous, but did assume one caused the other - your CountRef story above says it well though & fills an important missing link in my headspace.
It would be cool though if there were a way to 'get under the hood' and inspect the CountRefs of the vba engine

thx again
Glenn






 
Thanx for all guys - I've allocated lions share to GreymanMSC as creating a close method to explicitly clean up my references - esp cyclic ones is whats fixed the problem. Harfangs $.02+ helped my understanding on the whole issue though and couldn't go without recognition
thx again
Glenn