有没有这样的事情?VB6中的动态内存分配
我在谈论类似于C++ new
命令的内容,即分配需要显式释放内存的内存(或风险内存泄漏)。
我问,因为我记得有通过表单/控制/其他对象设置为Nothing
以前解决一些GDI泄漏问题,但不记得是什么,或者为什么现在......
我们曾经担心在VB6中开发时的内存管理?
有没有这样的事情?VB6中的动态内存分配
我在谈论类似于C++ new
命令的内容,即分配需要显式释放内存的内存(或风险内存泄漏)。
我问,因为我记得有通过表单/控制/其他对象设置为Nothing
以前解决一些GDI泄漏问题,但不记得是什么,或者为什么现在......
我们曾经担心在VB6中开发时的内存管理?
就VB6中的内存管理而言,有几个方面值得关注。
第一个是循环引用,其中子类指向父代,反之亦然。如果没有明确地将引用设置为Nothing,那么有时对于表单来说也是如此,特别是对象是Target对象的编辑器。再次确保一切设置为无效将解决问题。
基本原理是1)如果对象指向的任何东西是“活着的”,那么它将不会被垃圾收集。因此,当您将引用设置为循环引用的父对象时,该子节点处于活动状态,因此父节点不会收集垃圾信息,因为父节点仍处于活动状态,所以子节点不会收集垃圾信息。
与表格相同。如果您没有将编辑对象的对话框的目标属性设置为无效,只要目标对象处于活动状态,它就不会触发最后一系列事件。
这样做的最常见的副作用是你的应用程序将无法正常关闭和你的内存占用量将增长的应用程序使用的时间越长。
至于GDI泄漏,任何时候您使用使用句柄,指针的外部DLL。您将自己置于与C++相同的领域,以实现这些功能。所以你必须确保你遵循你使用的特定API或DLL的所有规则,这些规则通常包括明确地销毁你在完成之后创建的那些规则。
对于循环参考问题,有一个优雅的解决方案。而不是孩子直接引用父母,你使用代理。
首先做一个代理类的父对象。
Option Explicit Public Event GetRef(ByRef RHS As MyObject)
Public Function GetMyObject() As MyObject
Dim Ref As MyObject
RaiseEvent GetRef(Ref)
Set GetMyObject = Ref
End Function
然后是在父
Private WithEvents MyProxy As MyObjectProxy
Private Sub Class_Initialize()
Set MyProxy = New MyObjectProxy
End Sub
然后安装称为代理的只读属性来定义一个私有变量并实现GetRef事件。
Public Property Get Proxy() As MyObjectProxy
Set Proxy = MyProxy
End Property
Private Sub MyProxy_GetRef(RHS As MyObject)
Set RHS = Me
End Sub
对于需要参考的代码如下孩子或其他任何东西。
Private ParentProxy As MyObjectProxy
Public Property Get Parent() As MyObject
If ParentProxy Is Nothing Then
Set Parent = Nothing
Else
Set Parent = ParentProxy.GetRef
End If
End Property
Public Property Set Parent(RHS As MyObject)
If RHS Is Me Then
Set MyObjectProxy = Nothing
ElseIf Target Is Nothing Then
Set MyObjectProxy = Nothing
Else
Set MyObjectProxy = RHS.Proxy
End If
End Property
因为事件机制不设置引用或增加在任一COM引用计数反对它避免了整个循环引用的问题,是许多VB6程序员的祸根。
注:我是从源称这是代理,但由于安东尼的评论,我觉得这也符合调解模式的定义。它使用特定的VB6中心功能; Event API并不完全符合Mediator Pattern的精神。
另外还要认识到在.NET框架有等同VB6的事件API虽然它实现方式不同(代表等)
我想说你永远不必担心内存管理,但这不是真的。它在一定程度上取决于你的VB6代码运行的执行环境。当然,我已经看到了在COM +下运行的VB6类,如果它们完成时没有显式地将对象引用设置为Nothing,将会泄漏内存。
除了环境问题外,您在VB6类型系统中分配的内存通常会为您清理。我正在谈论您使用New关键字分配的内容。但有一个重要的例外,由rpetrich和其他人指出: -
由于VB用于管理分配对象的生存期的引用计数机制,如果您有任何循环引用,则可能会泄漏内存。例如,A-> B-> C-> A。如果你有这种情况,你可能需要自己发现它,并通过明确地将引用设置为Nothing来治愈它。我没有意识到任何有助于识别这类问题的工具。
当您使用其他语言编写的库时,会出现其他问题。你可能会新建一个用C++编写的COM对象,它在内部分配一些内存,并发现你必须调用特定的方法(如Close)来释放内存。也许这样一个COM对象会写得很糟糕,但其中很多都存在。
因此,有没有规律可循,除非是: -
由于VB6(和COM通常)使用参考计数,所以能够泄漏经由圆形物体引用。你应该编辑你的第二段来反映这 – rpetrich 2008-11-05 18:15:03
这就是众所周知的中介模式,值得添加到这个答案的文本。 – AnthonyWJones 2008-11-06 10:20:43