2

当我创建两个相互引用的字典对象时,即使我将它们明确设置为空,它们也会保留在内存中。以下代码消耗 >1 GB 内存

Dim i
For i = 1 to 100000
    leak
Next

Sub leak

    Dim a, b
    Set a = createObject("scripting.dictionary")
    Set b = createObject("scripting.dictionary")

    a.Add "dict1", b
    b.Add "dict2", a

    Set a = Nothing
    Set b = Nothing

end sub

这与某些垃圾收集无关(VBScript 不这样做)。证明:当我改变a.Add "dict1", ba.Add "dict1", "foo"改变b.Add "dict2", a内存消耗时a.Add "dict2", "bar",内存消耗保持在合理的范围内。

顺便说一句,当字典引用自身时也会发生这种情况:

Sub leak
    Dim a
    Set a = createObject("scripting.dictionary")
    a.Add "dict1", a
    Set a = Nothing
end sub

是否有可能以在内存中也被销毁的方式销毁像这些交叉引用字典这样的对象?

4

2 回答 2

2

找到字典的答案:使用该RemoveAll方法在引用超出范围之前摆脱所有键和值。经测试,无泄漏:

Sub leak

    Dim a, b
    Set a = createObject("scripting.dictionary")
    Set b = createObject("scripting.dictionary")

    a.Add "dict1", b
    b.Add "dict2", a

    a.RemoveAll
    b.RemoveAll

end sub 

如果您将字典用作keys(而不是items/ values),这也解决了循环引用问题,例如:

a.Add b, "dictionary b"
b.Add a, "dictionary a"
于 2013-02-28T13:58:27.780 回答
1

首先阅读Eric Lippert 的文章 (Explanation #2),然后将代码更改为

Dim i
For i = 1 to 100000
    leak
Next

Sub leak

    Dim a, b
    Set a = createObject("scripting.dictionary")
    Set b = createObject("scripting.dictionary")

    a.Add "dict1", b
    b.Add "dict2", a

    Set a("dict1") = Nothing
    Set b("dict2") = Nothing

end sub

和的引用计数通过离开子范围而减少,因为a您必须自己做。ba("dict1")b("dict2")

于 2013-02-28T13:45:33.027 回答