When I first started playing around with VBA, everything I read emphasized how important it was that when you initialized an object, you remembered to set it to nothing afterwards in order to 'release the memory'.
I did that for a while, but soon realized that this was not exactly correct.
As in many platforms, VBA has a mysterious garbage collector whose function is to return memory to the pool when it is no longer being referenced. The key here is 'referenced'. When you create a reference like
set b = new cBidule
then the new instance of a cBidule class becomes referenced by the variable b. It follows then if you remove the reference to it by
set b = Nothing
then that reference is removed and it then qualifies for the garbage collector's attention, but how to test?
VBA provides a special terminate and initialize function. When specified in your class, this will be called when it is created or terminated. If removing all references to an object destroys it, then we should see the class terminate being executed.
Here's my class code,
Here's a test
.. and here's the result
Perfect - exactly as expected. Setting bMain to nothing cause the object it references to be destroyed.
So let's say we have multiple references to the same object. In this case we reference the object with both bMain and bRef
Here's the result
Not quite the same result. This shows that the object is not released following setting bMain to nothing, since it is still being referenced by bRef. However the object is still released - when bMain goes out of scope. This is an important finding. It means that set x = nothing is irrelevant unless you need to recover the memory inside the same module.
The object memory will always be released when all variables accessing them have gone out of scope. There is no 'specialness' about setting a reference to nothing, except to accelerate the reduction of the reference count.
As discussed in Understanding Scope a public variable will be accessible outside the scope of a function. This means that a reference by a public variable will not go out of scope, and therefore the object memory will not be released
Here's the same thing, except our references are public
and the result shows that the object is never terminated, since the bRef object is public
Now if we make the bRef variable private, but leave the bMain public, since we set bMain to nothing and bRef will go out of scope automatically, we should see a class termination.
and that's exactly what happens
The garbage collector can be pretty basic. Lets say that we have two objects that reference each other.
here's the cBidule class
and the cWidget class
The cBidule class is going to contain a collection of cWidgets.
here's the test
and it works perfectly, terminating both instances as they go out of scope
But, let's say we also create a backlink to the parent bidule in each widget. This would be a pretty common thing to do.
what..?? they don't terminate on going out of scope
That's because the garbage collector still thinks there are references to each object - even though both have gone out of scope.
That's pretty amazing. So let's revisit whether setting things to nothing is of any value.
the result - as we've already established, setting to Nothing makes no difference.
The lesson here is that wherever there are backlinks between objects, you need to create a tearDown method to break those links, otherwise you will never release up the memory.
the updated bidule class
the updated widget class
and the test
now successfully releases the memory
For help and more information join our forum,follow the blog or follow me on twitter .
Services > Desktop Liberation - the definitive resource for Google Apps Script and Microsoft Office automation > Get Started Snippets > Understanding Scope >