jwcolby54
Active member
- Local time
- Today, 10:55
- Joined
- May 19, 2025
- Messages
- 305
I had a poster in one of my threads post that if I did some thing his way it would avoid a circular reference, and how circular references could cause memory leaks (true) and how if Access crashed the end of the (access) world could commence. Not so true but worth dealing with. The point though is that "circular references" are not the problem specifically, rather the problem is not cleaning up our references to things when done with them, in this specific case to a form. So... garbage collection in VBA, what is it and how does it work?
I hit up ChatGPT with the following so that we could have a starting point for a discussion on garbage collection in VBA. It is a subject often not well understood. We all understand the pitfalls of AI and ChatGPT, just know that is where the following information came from.
My question to ChatGPT:
I need an in depth discussion about the vba garbage collector. How it works and what triggers it. I am teaching classes , events etc at an in depth level and the garbage collector needs to be understood. I will be starting a thread on Access-Programmers to explain the subject. What you provide here will be the starting point for what will likely be a lively discussion. So clarity is key.
ChatGPT's response:
Great — let’s dive deep into how memory management and object destruction work in VBA (Visual Basic for Applications), commonly referred to as the VBA "garbage collector" even though it doesn’t quite work like a true garbage collector (e.g., in .NET or Java). This discussion will help your students and readers understand how and when objects are cleaned up in VBA, what pitfalls to avoid, and how circular references and event handlers can complicate things.
VBA does not use a traditional garbage collector. Instead, it uses a reference counting system to manage memory for objects.
Each VBA object has an internal reference count — a tally of how many variables (or other objects) are currently referring to it.
This is deterministic destruction — you know exactly when the object will be destroyed.
Object destruction is triggered when:
Reference counting fails when two objects reference each other — a circular reference — because each keeps the other alive.
Before setting your objects to Nothing, you should clear the internal references explicitly:
Events are delegates — they cause the class that listens for events to hold a reference to the event source.
Form1 has a reference to obj, but now obj raises events back to Form1, which means obj has a hidden reference to Form1. Even if you Set obj = Nothing, the circular reference persists.
Add a method on ClassA to null the event source:
Call it before destruction.
You can track object lifecycle using a counter and Debug.Print:
Or maintain a global counter:
OK. I am done presenting what ChatGPT wrote.
I hope this is useful to some of you. And I make no representation that it is useful or even correct. It is just information in the end.
I hit up ChatGPT with the following so that we could have a starting point for a discussion on garbage collection in VBA. It is a subject often not well understood. We all understand the pitfalls of AI and ChatGPT, just know that is where the following information came from.
My question to ChatGPT:
I need an in depth discussion about the vba garbage collector. How it works and what triggers it. I am teaching classes , events etc at an in depth level and the garbage collector needs to be understood. I will be starting a thread on Access-Programmers to explain the subject. What you provide here will be the starting point for what will likely be a lively discussion. So clarity is key.
ChatGPT's response:
Great — let’s dive deep into how memory management and object destruction work in VBA (Visual Basic for Applications), commonly referred to as the VBA "garbage collector" even though it doesn’t quite work like a true garbage collector (e.g., in .NET or Java). This discussion will help your students and readers understand how and when objects are cleaned up in VBA, what pitfalls to avoid, and how circular references and event handlers can complicate things.
What Is VBA’s "Garbage Collector"?
VBA does not use a traditional garbage collector. Instead, it uses a reference counting system to manage memory for objects.
✔ Core Mechanism:
Each VBA object has an internal reference count — a tally of how many variables (or other objects) are currently referring to it.
- When a variable is set to refer to an object (Set obj = New SomeClass), the reference count increases by 1.
- When that variable is set to Nothing or goes out of scope, the reference count decreases by 1.
- When the reference count drops to 0, VBA immediately destroys the object and releases the associated memory.
This is deterministic destruction — you know exactly when the object will be destroyed.
What Triggers Object Destruction?
Object destruction is triggered when:- All references to an object are cleared or go out of scope
Code:Sub Demo() Dim obj As New MyClass ' obj has reference count = 1 End Sub ' obj goes out of scope, count drops to 0 => destroyed
- You explicitly set the reference to Nothing
Code:Set obj = Nothing ' count drops to 0 => destroyed
- You overwrite a reference
Code:Set obj = New MyClass ' old object: count drops to 0, destroyed
Circular References: The Achilles Heel
Reference counting fails when two objects reference each other — a circular reference — because each keeps the other alive.Example:
Code:
' ClassA has a reference to ClassB, and vice versa
'--- ClassA
Public Partner As ClassB
Private Sub Class_Terminate()
Debug.Print "ClassA terminated"
End Sub
'--- ClassB
Public Partner As ClassA
Private Sub Class_Terminate()
Debug.Print "ClassB terminated"
End Sub
Sub CreateLeak()
Dim a As New ClassA
Dim b As New ClassB
Set a.Partner = b
Set b.Partner = a
' Break external refs:
Set a = Nothing
Set b = Nothing
' Reference counts are still > 0 => memory leak
End Sub
Fix: Manual breaking of the circular reference
Before setting your objects to Nothing, you should clear the internal references explicitly:
Code:
Set a.Partner = Nothing
Set b.Partner = Nothing
Set a = Nothing
Set b = Nothing
VBA provides a pseudo-destructor in class modules:
Code:
Private Sub Class_Terminate()
' Cleanup code here
End Sub
- This fires automatically when the reference count hits 0.
- You cannot call Class_Terminate directly.
- It’s the place to:
- Close files
- Release resources
- Break circular references (if needed)
- Unhook event sinks
Events and Memory Leaks
Events are delegates — they cause the class that listens for events to hold a reference to the event source.Common leak scenario:
Code:
' Form1 creates ClassA and hooks to its events
Dim WithEvents obj As ClassA
Private Sub Form_Load()
Set obj = New ClassA
End Sub
Form1 has a reference to obj, but now obj raises events back to Form1, which means obj has a hidden reference to Form1. Even if you Set obj = Nothing, the circular reference persists.
Fix: Unhook event sinks manually
Code:
Set obj = Nothing ' leaks Form1
Add a method on ClassA to null the event source:
Code:
Public Sub Unhook()
Set EventTarget = Nothing
End Sub
Call it before destruction.
VBA's "Garbage Collector" in Summary
Concept | Description |
---|---|
Type | Reference-counted memory management |
Destruction Timing | Immediate, deterministic (when ref count = 0) |
Destructor | Class_Terminate |
Leaks? | Yes, due to circular references or poorly handled events |
Explicit Cleanup? | Required when circular references or event sinks exist |
Teaching Tips
- Emphasize reference tracing. Draw diagrams showing object dependencies.
- Reinforce that Set x = Nothing is about breaking links — it’s not “destroying” anything on its own.
- Explain how static variables can also keep objects alive longer than intended.
- Discuss Debug.Print or log output in Class_Terminate to track lifecycle.
Bonus: Detecting Leaks
You can track object lifecycle using a counter and Debug.Print:
Code:
Private Sub Class_Initialize()
Debug.Print "Object created"
End Sub
Private Sub Class_Terminate()
Debug.Print "Object destroyed"
End Sub
Or maintain a global counter:
Code:
Public gLiveCount As Long
Private Sub Class_Initialize()
gLiveCount = gLiveCount + 1
End Sub
Private Sub Class_Terminate()
gLiveCount = gLiveCount - 1
End Sub
OK. I am done presenting what ChatGPT wrote.
I hope this is useful to some of you. And I make no representation that it is useful or even correct. It is just information in the end.
Last edited: