Detecting references (gdi object/memory leak)

According to and I see that RB/Xojo doesn’t do garbage collection, but

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
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
      End If
    Next t
    mt = m_mt
    ReDim m_mt.m_wrArr(-1)
    ReDim m_mt.m_strArrFullName(-1)
    m_mt = Nil
  End If

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
End If


Then you add this line to each constructor of each suspect class:

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

Happy hunting