VBA垃圾收集器详细信息

Jon*_*tus 17 vb6 vba

我发现自己最近不得不写一些VBA代码,只是想知道是否有人曾经遇到过有关VBA垃圾收集器如何工作的任何细节?.Net GC确实有很好的记录,但我在VBA GC上找不到一丝细节,除了模糊的提到它是一个参考计数器.我认为它与VB6 GC非常相似,但无法找到任何相关信息.

具体来说,我有兴趣知道:

  • 触发GC的原因
  • 它使用什么算法(例如,收集生成?)
  • 如何处理循环引用(如果有的话)?
  • 有没有办法监控其运作

这比任何特别需要知道的更多是出于好奇,任何洞察都非常感激!

Kon*_*lph 15

以下假设VBA 仍然使用VB6中使用的相同垃圾收集机制(它很可能会这样做).

VB6使用了引用计数GC.当对给定对象的最后一次引用设置为时,确定性地触发GC Nothing.设置本地引用Nothing是不必要的,这是因为它们超出范围.

每个对象都实现一个COM接口,负责处理该对象的引用计数.对象引用的每个赋值都更新所涉及引用的引用计数器(即先前引用的旧对象的计数器递减,并且新对象的计数器递增).当引用计数器达到0时,对象被垃圾收集.

因此,在VBA应用程序的生命周期内,永远不会收集循环引用中的对象.更重要的是,VBA没有提供打破循环引用的方法.在VB6中,可以通过WinAPI函数实现弱引用.

  • @Jon:不幸的是,这个谣言并非完全没有根据.VB6似乎有一个错误,可能导致类成员变量中的一些悬空引用(尽管不是局部变量).我不知道这个bug的确切来源是否曾被追踪过,但是使用`Class_Terminate`方法将所有成员设置为'Nothing`已成为最佳实践. (6认同)
  • "... VB可以在End Sub行更快地清除变量,而不是从代码中清除变量,即使你明确地发布你的引用,它也会检查变量.你所做的任何努力都是重复的." Matthew Curland,高级VB6,p110. (6认同)
  • @Bob:取决于你问的是谁,两个定义都存在(我猜你的问题是在COM引用计数中,没有一个中央GC"服务"提供GC,而是每个对象都有自己的收集机制内置).但是我想我在答案中明确了*VBA中发生了什么*,无论是否想要将其称为GC. (5认同)
  • VBA根本不使用垃圾收集.当对象的引用计数变为0时,释放对象.这不是垃圾收集. (3认同)
  • @wqw:实现`Class_Terminate` 方法不会破坏循环依赖,因为永远不会调用该方法。当然,您可以实现一个*手动调用的*`Terminate` 方法,如果这就是您所指的。至于这是否称为“垃圾收集”,再次:两个定义都存在。反对这一点是小题大做。无论这个解释是否“有趣”——它都是准确的。这才是最重要的。 (2认同)
  • @Lunatik:边缘情况是在DAO(不是ADO)中:"[DAO提供]另一个糟糕的拆解代码示例.DAO具有必须以正确顺序调用的Close方法,并且必须以正确的顺序释放对象好吧(例如,在数据库之前的Recordset).这个单一的糟糕对象模型行为导致了VB泄漏内存的误解,除非你在函数末尾显式地将所有局部变量设置为空.这是一个完全错误的概念.精心设计的物体模型......" (2认同)