处理vb6对象-一个令人惊讶的问题

处理vb6对象-一个令人惊讶的问题,vb6,Vb6,我在vb6中“发明”了一种链表技术,将指针放在对象内: Class FooBar: Public ptr As FooBar 现在我只拿着一个指向列表头部的指针,在head.ptr中指向下一个对象,head.ptr.ptr指向下一个对象,以此类推 当我想销毁列表时,我只使用Set Head=Nothing,这会导致clearing Head.ptr,这反过来会触发clearing Head.ptr.ptr等,从而导致一个空列表(我实际上是通过在Class_Terminate事件中放置断点来检查

我在vb6中“发明”了一种链表技术,将指针放在对象内:

Class FooBar:
Public ptr As FooBar
现在我只拿着一个指向列表头部的指针,在
head.ptr
中指向下一个对象,
head.ptr.ptr
指向下一个对象,以此类推

当我想销毁列表时,我只使用
Set Head=Nothing
,这会导致clearing Head.ptr,这反过来会触发clearing Head.ptr.ptr等,从而导致一个空列表(我实际上是通过在Class_Terminate事件中放置断点来检查它)

这很好,很整洁,直到我在列表中有10000个对象。现在,行
Set Head=Nothing
导致“堆栈内存不足”错误,之后IDE崩溃

事实证明,vb6递归地清除对象(即使我没有类_Terminate事件,也会发生这种情况)

所以我想我应该用某种循环“手动”销毁列表。但我想不出一个方法来实现,因为在循环中使用指针并将其设置为Nothing会。。。没有,因为它将AddRef添加到对象


我该怎么办?

我能理解为什么会出现堆栈溢出。您正在隐式调用IUnknown接口的Release()方法,该方法调用内部VB destroy方法,该方法清除所有内部状态,包括指向下一项的变量,然后该变量调用Release(),等等

为了避免堆栈溢出问题,最好实现双链接列表,并始终保存指向列表末尾的指针。但是现在你会遇到循环引用的问题,除非你有一个具体的处理方法,否则什么都不会清除


您也可以使用VBA.Collection对象,这是我被告知的(在《硬核Visual Basic内部是一个双链接列表》一书中)。

我终于找到了一种手动销毁列表的方法

一个有点棘手但有效的解决方案

我首先向类中添加一个小方法,该方法在不移除对象的情况下清除内部指针

Class FooBar:
Public ptr As FooBar

Public Function SafeRemove() As FooBar
Set SafeRemove = ptr
Set ptr = Nothing
End Function
在模块中:

Sub ClearList()
While Head Is Nothing = False
    Set Head = Head.SafeRemove
Wend
End Sub

“我该怎么办?”不这样滥用语言将是一个开始。使用数组或集合。(或带有显式处理例程的传统链表。)设置Head=nothing如何准确地“触发”所有子PTR的级联nothing设置?我看不出什么机制会导致这种情况自动发生。您可能应该发布更多的代码,这样我们才能真正评估正在发生的事情。@uuddrlrss:每当清除对对象的最后一个引用时,该对象就会被删除。因此,当我删除对象“Head”时,它不再指向Head.ptr对象,因此Head.ptr也必须删除,依此类推。正如我所说,我已经用一个断点确认了这一点。实际上,没有其他与该主题相关的代码。我只是初始化新对象并将最后一个.ptr分配给它们。好的,但这不一定是递归完成的,尽管它必须迭代完成。如果VB6真的以递归方式执行此操作,并导致堆栈错误,我会感到非常惊讶。发生这种情况时,您的链接列表的大小是多少?在这种情况下,双链接列表没有任何作用,如果有什么作用的话-它会使情况更加恶化…集合是一个很好的选择。但这个问题必须有一个解决方案,不是吗?集合不如低级c样式的链表灵活。例如:它不容易排序。标准集合对象可能不容易排序,但您可以创建易于排序的自定义集合。尽管术语不同,但VB6中的自定义集合本质上是创建一个继承和扩展标准集合对象的强类型集合。整洁!因此
Set Head=Head.SafeRemove
释放
Head
,但保持
ptr
仍处于活动状态,以避免再次发生
终止
事件。