我在调试VB6代码中的内存泄漏时发现的所有建议都集中在GDI泄漏上。然而,在我的情况下,证据表明我没有GDI泄漏,但可能确实有内存泄漏。什么可能是导致这种泄漏的可能候选人,和/或帮助我确定导致此程序的部分程序的好工具?
答案 0 :(得分:2)
不幸的是,VB6没有足够的调试工具来检测对象泄漏。我通常在每个类,表单或用户控件中使用几个辅助函数在我自己实现实例簿记。基本模式就像这样
Private Const MODULE_NAME As String = "<<class_name_here>>"
#If DebugMode Then
Private m_sDebugID As String
#End If
#If DebugMode Then
Private Sub Class_Initialize()
DebugInstanceInit MODULE_NAME, m_sDebugID, Me
End Sub
#End If
#If DebugMode Then
Private Sub Class_Terminate()
DebugInstanceTerm MODULE_NAME, m_sDebugID
End Sub
#End If
帮助程序函数DebugInstanceInit
生成下一个顺序ID并将其分配给m_sDebugID
,然后将模块名称和ObjPtr(Me)
存储在集合中,并以id键入。
帮助程序函数DebugInstanceTerm
使用m_sDebugID
作为关键字从集合中删除条目。
这样,在应用程序执行的每个时刻,您都可以转储此实例集合,并识别已分配但仍未终止的对象的计数和类型。如果表单的连续打开和关闭会增加对象计数,则可能是由于循环引用(例如collection-&gt;条目和entry-&gt;集合)而泄漏对象。
大多数框架和其他语言都内置了这种簿记(至少在调试版本中),但遗憾的是VB6对源代码元数据(MODULE_NAME,FUNC_NAME,LINE_NUMBER)和对象生存期管理的支持很少。缺乏实现继承也在这里受到伤害。
答案 1 :(得分:1)
通常,您必须注意循环引用。在VB6中,只要在某处引用了对象,对象就会保留在内存中。因此,如果您有一个对象类型变量作为表单的成员(例如),那么它将在内存中,直到该表单被终止(除非您明确地将其设置为早于当然)。那个参考链可以非常深入:
这里,FormA将ObjectB和ObjectC保留在内存中:
FormA - &gt; ObjectB - &gt; ObjectC
你需要注意的是这样的事情:
FormA - &gt; ObjectB&lt; - &gt; ObjectC
ObjectB具有对ObjectC的引用,而ObjectC具有对ObjectB的后引用或父引用。即使FormA被终止或以其他方式清除它对ObjectB的引用,ObjectB和ObjectC将永远存在并代表内存泄漏。
答案 2 :(得分:1)
查找内存泄漏的好工具是删除程序。你可以尝试一下。并检查一件事 - 是否还有GDI泄漏。你必须确定!