Currently we have an object that refuses to release, so we assume it is referenced somewhere, but we are unable to find what is referencing this object.
Is there any way to see what references an object, and if not, what techniques would you all suggest to narrow down the problem.
Thanks in advance for any pointers.
You’ll probably have to walk through all the objects in the runtime using object iterator & use introspection
Do you have enough information to know which kind of class , instance name etc ?
That way with introspection you can at least put code in to break when you get to that kind of instance
Yes, we know it’s a (self made) control that isn’t getting released somehow.
So we know the name and that it’s one of our own controls.
I guess it’s time to learn about the runtime and introspection
Introspection couldn’t solve this because we can get a list of objectids and a list of objects through introspection. But we couldn’t get an object from the objectid or and objectid from an actual object.
I found a property mClassRef which could be translated to an objectid maybe, but it wasn’t accessible by code.
Eventually found a (1) circular reference through use of this newly fabricated code:
Class: clsMemoryTrap
Property: m_strArrFullName() As String
Property: m_wrArr() As WeakRef
Shared Property: m_mt As clsMemoryTrap
Shared Method: Start()
{ #if DebugBuild
If IsNull(m_mt) Then
m_mt = New clsMemoryTrap
End If #endif
}
Shared Method: Stop()
{ #if DebugBuild
Dim t As Integer
Dim mt As clsMemoryTrap
If Not IsNull(m_mt) Then
For t = m_mt.m_wrArr.Ubound To 0 Step -1
If IsNull(m_mt.m_wrArr(t)) Or IsNull(m_mt.m_wrArr(t).Value) Then
m_mt.m_wrArr.Remove(t)
m_mt.m_strArrFullName.Remove(t)
End If
Next t
mt = m_mt
Break
ReDim m_mt.m_wrArr(-1)
ReDim m_mt.m_strArrFullName(-1)
m_mt = Nil
End If
#endif
}
Shared Method: GuardObject(o As Object)
{ #if DebugBuild
Dim ot As Introspection.TypeInfo
Dim strName As String
If Not IsNull(m_mt) Then
m_mt.m_wrArr.Append(New WeakRef(o))
ot = Introspection.GetType(o)
strName = ot.FullName
m_mt.m_strArrFullName.Append(strName)
End If
#endif
}
Then you add this line to each constructor of each suspect class:
clsMemoryTrap.GuardObject(Self)
You add a method to execute start and stop in debug
Run your application
Execute Start
'Do a bunch of suspect actions and finish in a state where all objects in memory you made should be destroyed
Execute Stop
The code breaks and you get a list of objects that should not exist anymore