Excel 当链表包含超过6000个元素时,释放链表内存时出现堆栈空间不足错误
我在VBA中有一个双链表,其中有一个Class_Terminate子例程,它通过元素循环,将它们断开,以便释放内存。当我得到错误28:堆栈空间不足时,在列表包含超过6500个元素之前,所有这些都可以正常工作 我没有看到任何明显的递归,Class_Terminate子例程的堆栈空间不应该随着元素的数量而增加,但是谁知道VBA解释器在做什么呢 有什么想法吗?下面是要复制的所有代码 CQueue类模块 CQElement类模块 测试子程序 CSomeClass类模块 Terminate方法未完全释放对链接列表的所有引用,因此列表对象未被分发 换成这个Excel 当链表包含超过6000个元素时,释放链表内存时出现堆栈空间不足错误,excel,stack-overflow,vba,Excel,Stack Overflow,Vba,我在VBA中有一个双链表,其中有一个Class_Terminate子例程,它通过元素循环,将它们断开,以便释放内存。当我得到错误28:堆栈空间不足时,在列表包含超过6500个元素之前,所有这些都可以正常工作 我没有看到任何明显的递归,Class_Terminate子例程的堆栈空间不应该随着元素的数量而增加,但是谁知道VBA解释器在做什么呢 有什么想法吗?下面是要复制的所有代码 CQueue类模块 CQElement类模块 测试子程序 CSomeClass类模块 Terminate方法未完全释放对
Private Sub Class_Terminate()
If Not m_start Is Nothing Then
If m_length > 1 Then
Set m_start = m_start.m_next
Do While Not m_start Is m_end
Set m_start.m_prev.m_prev = Nothing
Set m_start.m_prev.m_next = Nothing
Set m_start.m_prev = Nothing
Set m_start = m_start.m_next
Loop
End If
Set m_start.m_prev = Nothing
Set m_start.m_next = Nothing
Set m_start = Nothing
Set m_end = Nothing
End If
End Sub
很有趣,克里斯。您的析构函数解决了堆栈溢出问题,谢谢。然而,并不是因为它完全释放了所有引用,所以原始析构函数也完全释放了所有引用。您提供的析构函数与原始析构函数的区别在于发布顺序。原始方案首先发布链接列表,然后是元素,您的方案首先发布元素,然后是链接列表本身。关于为什么顺序会对堆栈空间产生影响,有什么想法吗?顺便说一句,将语句集element.m_prev.m_next=Nothing添加到原始析构函数中可以实现相同的效果thing@OldSchool原始终止例程不会释放m_start或m_end。它还只将m_prev元素设置为Nothing,保留m_next元素不变。因此,没有发布任何链接列表。抱歉,这是不正确的。当列表被释放时,m_start和m_end被释放,因为列表是唯一指向它们的东西。所有节点也是如此。一旦你切断了反向链接,唯一指向它们的就是列表,所以当它消失时,它们都消失了。只需运行一个带有调试的测试。打印类_Terminate例程中的语句,以便自己查看。因此,问题的关键仍然没有答案。i、 e.在堆栈帧应该是固定大小的情况下,为什么迭代会占用堆栈空间?为什么物体释放的顺序似乎很重要?
Option Explicit
Public item As Variant
Public m_next As CQElement
Public m_prev As CQElement
Public Sub testQueueBounds()
Dim elementCount As Long: elementCount = 7000
Dim q As CQueue: Set q = New CQueue
q.maxLength = elementCount
Dim element As CSomeClass
Dim i As Long
For i = 1 To elementCount
Set element = New CSomeClass
Call q.enq(element)
Next i
Set q = Nothing
End Sub
Option Explicit
'This is entirely empty
Private Sub Class_Terminate()
If Not m_start Is Nothing Then
If m_length > 1 Then
Set m_start = m_start.m_next
Do While Not m_start Is m_end
Set m_start.m_prev.m_prev = Nothing
Set m_start.m_prev.m_next = Nothing
Set m_start.m_prev = Nothing
Set m_start = m_start.m_next
Loop
End If
Set m_start.m_prev = Nothing
Set m_start.m_next = Nothing
Set m_start = Nothing
Set m_end = Nothing
End If
End Sub