When must I set a variable to “Nothing” in VB6?在我的一种VB6表单中,我创建了其他几个Form对象,并将它们存储在成员变量中。
我注意到,每当创建(销毁)此(父)表单时,我都会泄漏内存。 我是否有必要将这些成员变量分配给 通常,什么时候需要?
已解决:当我在有问题的表单上执行 @Matt Dillard-设置这些为空不会解决内存泄漏问题吗? VB6没有正式的垃圾收集器,更像@Konrad Rudolph所说的。 在我看来,实际上调用表单上的unload似乎是确保清理主表单以及确保每个子表单清理其行为的最佳方法。 我用一个空白项目和两个空白表格进行了测试。
运行后,两种形式都可见。将frm设置为空无一事。 将frtign设置为空后,打开此表单的唯一句柄是通过引用。
我能正确看到问题吗?
实际上,VB6就像C ++一样实现RAII,这意味着本地声明的引用会在块的末尾自动设置为 VB中的对象具有引用计数。这意味着一个对象将保留其他对象变量对它的引用的计数。当没有对对象的引用时,对象将被垃圾收集(最终)。此过程是COM规范的一部分。 通常,当本地实例化的对象超出范围时(即退出子对象),其引用计数将减少1,换句话说,引用该对象的变量将被破坏。因此,在大多数情况下,退出Sub时无需显式设置等于Nothing的对象。 在所有其他情况下,必须将对象变量显式设置为Nothing,以减少其引用计数(减1)。将对象变量设置为Nothing,不一定会破坏对象,必须将ALL引用设置为Nothing。对于递归数据结构,此问题可能变得尤为严重。 另一个陷阱是在对象变量声明中使用New关键字时。仅在首次使用时创建对象,而不是在使用New关键字时创建对象。每当声明的引用计数为零时,在声明中使用New关键字将在首次使用时重新创建该对象。因此,将对象设置为Nothing可能会破坏它,但是如果再次引用该对象,则会自动重新创建该对象。理想情况下,您不应使用New关键字声明,而应使用不具有此复活行为的New运算符进行声明。 @马丁
With / End With不能像Using语句那样工作,它不会在语句末尾"处分"。 With / End With在VB 6中的工作方式与在VB.Net中一样,基本上是一种用于快捷方式调用对象属性/方法的方法。例如
这里没有提到的重要一点是,如果没有其他对对象的引用(引用计数为零),则将对象引用设置为Nothing将导致对象的析构函数运行(如果类是用VB编写的,则为Class_Terminate)。 )。 在某些情况下,尤其是在使用RAII模式时,终止代码可以执行可能引起错误的代码。我相信某些ADODB类就是这种情况。另一个示例是封装文件I / O的类-如果文件仍处于打开状态,则Class_Terminate中的代码可能会尝试刷新和关闭文件,这可能会引发错误。 因此,请务必注意,将对象引用设置为Nothing会引发错误,并相应地进行处理(确切地说,这将取决于您的应用程序-例如,您可能会在"设置... =否"。 我前一段时间有类似的问题。我似乎认为这也会阻止该应用关闭,但在这里可能适用。 我拉起旧代码,它看起来像:
卸载m_frm1可能更安全。而不仅仅是将其设置为空。 将VB6引用设置为Nothing可以减少VB对于该对象的引用计数。当且仅当计数为零时,对象才会被销毁。 不要以为仅仅因为设置为Nothing就可以像在.NET中那样"收集垃圾" VB6使用参考计数器。 鼓励您将可引用C / C ++代码和类似内容的实例化对象设置为" Nothing"。自从接触VB6以来已经很长时间了,但是我记得没有将文件和资源设置为空。 无论哪种情况,它都不会受到伤害(如果还没有的话),但这并不意味着该对象将被销毁。 VB6有一个" With / End With"语句,其工作方式类似于C#.NET中的Using()语句。当然,拥有的东西越少,对您越有利。 请记住,无论哪种情况,有时创建大型对象都比保持引用有效并重用它昂贵。 严格说来永远不会,但是它为垃圾收集器提供了清理工作的强大提示。 通常,每次创建对象时都要这样做。 |