Search code examples
vb6adodbreference-counting

How can I get a reference count to an ADODB recordset object?


I'm investigating a memory leak in some old VB6 code that seems to be related to recordset objects, so I'm trying to get the reference counts on the objects. I found some code online that will give a count of references to an object, and it works for a home-grown class. But when I try to apply it to ADODB recordset objects, the count is always 1492925242. I've tried this in the existing app and then in a dummy app - always comes back with the same number (unless there are no references, then it's 0).

Here's the code that gets the reference count:

    Private Declare Sub RtlMoveMemory Lib "kernel32" (dest As Any, src As Any, ByVal nbytes As Long)

Function objRefCnt(obj As IUnknown) As Long 
    If Not obj Is Nothing Then
       RtlMoveMemory objRefCnt, ByVal ObjPtr(obj) + 4, 4
       objRefCnt = objRefCnt - 2
    Else
       objRefCnt = 0
    End If
End Function

Here's the code that calls it on ADODB recordsets:

    Sub main()
    Dim obj_1 As ADODB.Recordset
    Dim obj_2 As ADODB.Recordset

    Debug.Print objRefCnt(obj_1) ' 0

    Set obj_1 = New ADODB.Recordset
    Debug.Print objRefCnt(obj_1) ' 1

    Set obj_2 = obj_1
    Debug.Print objRefCnt(obj_1) ' 2
    Debug.Print objRefCnt(obj_2) ' 2

    Set obj_2 = New ADODB.Recordset
    Debug.Print objRefCnt(obj_1) ' 1
    Debug.Print objRefCnt(obj_2) ' 1
    End Sub

This returns the following:

 0
 1492925242 
 1492925242 
 1492925242 
 1492925242 
 1492925242

But when I added a dummy class called Class1 that has a single property (an integer), and create obj_1 and obj_2 as Class1 objects, I get this:

 0 
 1 
 2 
 2 
 1 
 1 

Any ideas on how I can get a reference count on the ADODB recordsets? Thanks in advance.


Solution

  • The code you found assumes the reference count is stored inside the object at offset 4. There is no such requirement. IUnknown defines methods, not where private variables must be stored (and the reference count is a private variable of an object).

    The way to get the reference count (for testing purposes only) is to call IUnknown.Release.

    In order to do that from VB6, find olelib.tlb on the Internet (Edanmo's OLE interfaces & functions), reference it, and have

    Public Function GetRefCount(ByVal obj As olelib.IUnknown) As Long
      obj.AddRef
      GetRefCount = obj.Release - 2
    End Function
    
    Dim r1 As ADODB.Recordset
    Dim r2 As ADODB.Recordset
      
    Set r1 = New ADODB.Recordset
    Set r2 = r1
      
    MsgBox GetRefCount(r1)  ' 2