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.
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