如何获得 ADODB 记录集对象的引用计数?
How can I get a reference count to an ADODB recordset object?
我正在调查一些似乎与记录集对象相关的旧 VB6 代码中的内存泄漏,因此我正在尝试获取对象的引用计数。我在网上找到了一些代码,可以计算一个对象的引用数,它适用于自制的 class。但是当我尝试将它应用于 ADODB 记录集对象时,计数始终为 1492925242。我已经在现有应用程序中尝试过,然后在虚拟应用程序中尝试过 - 总是返回相同的数字(除非没有引用,否则它是0).
这是获取引用计数的代码:
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
下面是在 ADODB 记录集上调用它的代码:
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
这个 returns 以下:
0
1492925242
1492925242
1492925242
1492925242
1492925242
但是当我添加一个名为 Class1
的虚拟 class 时,它有一个 属性(整数),并创建 obj_1
和 obj_2
作为Class1
个对象,我得到这个:
0
1
2
2
1
1
关于如何获取 ADODB 记录集的引用计数的任何想法?
提前致谢。
您找到的代码假定引用计数存储在对象内部的偏移量 4 处。没有这样的要求。 IUnknown
定义了方法,不是必须存放私有变量的地方(引用计数是对象的私有变量)
获取引用计数的方法(仅供测试)是call IUnknown.Release
.
为了从 VB6 做到这一点,find olelib.tlb
在 Internet 上(Edanmo 的 OLE 接口和函数),参考它,并且
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
m_dwRefCount
ADODB.Recordset
个实例的成员变量出现在偏移量 16。
试试这个 objRefCnt
替换:
Private Declare Sub RtlMoveMemory Lib "kernel32" (dest As Any, src As Any, ByVal nbytes As Long)
Function RecordsetRefCnt(rs As Recordset) As Long
If Not rs Is Nothing Then
RtlMoveMemory RecordsetRefCnt, ByVal ObjPtr(rs) + 16, 4
RecordsetRefCnt = RecordsetRefCnt - 1
Else
RecordsetRefCnt = 0
End If
End Function
仅供参考,这是一个基于 AddRef
/Release
的 GetRefCount
实现,没有额外的类型库
Private Declare Function DispCallFunc Lib "oleaut32" (ByVal pvInstance As Long, ByVal oVft As Long, ByVal lCc As Long, ByVal vtReturn As VbVarType, ByVal cActuals As Long, prgVt As Any, prgpVarg As Any, pvargResult As Variant) As Long
Public Function GetRefCount(pUnk As IUnknown) As Long
Const CC_STDCALL As Long = 4
Dim vResult As Variant
Call DispCallFunc(ObjPtr(pUnk), 1 * 4, CC_STDCALL, vbLong, 0, ByVal 0, ByVal 0, 0)
Call DispCallFunc(ObjPtr(pUnk), 2 * 4, CC_STDCALL, vbLong, 0, ByVal 0, ByVal 0, vResult)
GetRefCount = vResult - 2
End Function
我正在调查一些似乎与记录集对象相关的旧 VB6 代码中的内存泄漏,因此我正在尝试获取对象的引用计数。我在网上找到了一些代码,可以计算一个对象的引用数,它适用于自制的 class。但是当我尝试将它应用于 ADODB 记录集对象时,计数始终为 1492925242。我已经在现有应用程序中尝试过,然后在虚拟应用程序中尝试过 - 总是返回相同的数字(除非没有引用,否则它是0).
这是获取引用计数的代码:
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
下面是在 ADODB 记录集上调用它的代码:
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
这个 returns 以下:
0
1492925242
1492925242
1492925242
1492925242
1492925242
但是当我添加一个名为 Class1
的虚拟 class 时,它有一个 属性(整数),并创建 obj_1
和 obj_2
作为Class1
个对象,我得到这个:
0
1
2
2
1
1
关于如何获取 ADODB 记录集的引用计数的任何想法? 提前致谢。
您找到的代码假定引用计数存储在对象内部的偏移量 4 处。没有这样的要求。 IUnknown
定义了方法,不是必须存放私有变量的地方(引用计数是对象的私有变量)
获取引用计数的方法(仅供测试)是call IUnknown.Release
.
为了从 VB6 做到这一点,find olelib.tlb
在 Internet 上(Edanmo 的 OLE 接口和函数),参考它,并且
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
m_dwRefCount
ADODB.Recordset
个实例的成员变量出现在偏移量 16。
试试这个 objRefCnt
替换:
Private Declare Sub RtlMoveMemory Lib "kernel32" (dest As Any, src As Any, ByVal nbytes As Long)
Function RecordsetRefCnt(rs As Recordset) As Long
If Not rs Is Nothing Then
RtlMoveMemory RecordsetRefCnt, ByVal ObjPtr(rs) + 16, 4
RecordsetRefCnt = RecordsetRefCnt - 1
Else
RecordsetRefCnt = 0
End If
End Function
仅供参考,这是一个基于 AddRef
/Release
的 GetRefCount
实现,没有额外的类型库
Private Declare Function DispCallFunc Lib "oleaut32" (ByVal pvInstance As Long, ByVal oVft As Long, ByVal lCc As Long, ByVal vtReturn As VbVarType, ByVal cActuals As Long, prgVt As Any, prgpVarg As Any, pvargResult As Variant) As Long
Public Function GetRefCount(pUnk As IUnknown) As Long
Const CC_STDCALL As Long = 4
Dim vResult As Variant
Call DispCallFunc(ObjPtr(pUnk), 1 * 4, CC_STDCALL, vbLong, 0, ByVal 0, ByVal 0, 0)
Call DispCallFunc(ObjPtr(pUnk), 2 * 4, CC_STDCALL, vbLong, 0, ByVal 0, ByVal 0, vResult)
GetRefCount = vResult - 2
End Function