2

相互に参照する 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", bますa.Add "dict1", "foo"b.Add "dict2", aa.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 の記事 (説明 #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 に答える