GetRefのメモリ消費量(ガベージコレクション)がKB4525236で変更されました


11

Windows 2016サーバー/ Windows 10クライアントにKB4525236をインストールした後、メモリ不足の問題が発生します。このセキュリティ修正により、から関数を呼び出すときにメモリがガベージコレクションされる瞬間が変わったようGetRefです。

プレKB4525236

を通じて呼び出された関数で作成された各インスタンスGetRefは、インスタンス変数が次のように設定されるとすぐにガベージコレクションされます。nothing

KB4525236の投稿

関数で作成された各インスタンスGetRefはメモリに残り、関数全体が完了するまでガベージコレクションされません。ループでインスタンスを作成すると、特に32ビットプロセスでは、これがすぐに加算されてメモリ不足につながる可能性があります。

ご質問

  • オンラインで関連するものを見つけることができないので、同じ問題が発生している他の人から確認を得たいと思います。スクラッチを
    編集これは同じ問題ですが、現時点で解決策はありません
    (KB4524570(2019年11月12日)Windows 10 1903以降のvbscript.dll class_terminateバグ)
  • 誰かが検証して実行可能なソリューションを知っていれば、それは素晴らしいことです。

POC

KB4525236がインストールされているデバイスで実行されている次のスクリプトは、次の場合のガベージコレクションの違いを示しています。

  • 直接呼び出されます:最初のインスタンスが破棄されたにのみ2番目のインスタンスが作成されます(これは私たちの望ましい動作です)
  • コールスルーGetRef:最初のインスタンスが破棄される前に 2番目のインスタンスが作成されるため、メモリを使用する2つのインスタンスがあります。

名前を付けて保存:KB4525236.vbs
として実行:wscript KB4525236.vbs

Dim Name, Log

Class IDummyInstance
  Dim FName
  Sub Class_Initialize
    FName = Name
    Log = Log & "Initialize " & FName & VbNewLine
  End Sub
  Sub Class_Terminate
    Log = Log & "Terminate " & FName & vbNewLine
  End Sub
End Class

Sub CreateDestroyTwoInstances
  Dim DummyInstance
  Name = "First Instance"
  Set DummyInstance = New IDummyInstance
  Set DummyInstance = Nothing
  Name = "Second Instance"
  Set DummyInstance = New IDummyInstance
  Set DummyInstance = Nothing
End Sub

Log = "(1) Direct Call :" & VbNewLine
Call CreateDestroyTwoInstances

Log = VbNewLine & Log & "(2) GetRef Call :" & vbNewLine
Set GetRefCall = GetRef ("CreateDestroyTwoInstances")
Call GetRefCall

MsgBox Log

1
@Lankymart-問題は、で作成されたインスタンスが終了するGetRef()までガベージコレクションされないことGetRef()です。それはそれが何であったかとは異なります。GetRef()1000のインスタンスを作成することによって呼び出される関数GetRef()があり、それらは過去までメモリを蓄積し続けますが、過去には、でループを実行している間に解放されましたGetRef()
Lieven Keersmaekers

1
明確にしていただきありがとうございます。そのtbhについて何ができるかわかりません。だれかが知っているとしたら、VBScriptを作成した元のチームで働いていた@ eric-lippertだと想像してください。
Lankymart

2
私は、KB4525236またはKB4524570なしのWindows 7であなたが説明する動作を持っています(どうやらWindows 7でそれを行う別のKBがあるようです)。それでも、VBScriptにはガベージコレクションはありません。参照カウントがゼロになったら、オブジェクトを破棄する必要あります。それが発生しない場合は、GCの別の機能ではなく、エンジンのバグです。
GSerg

2
これは、明示的な変数がなくても当てはまります。2つのWith New IDummyInstance : End Withブロックは、「最初のインスタンスの初期化、2番目のインスタンスの初期化、最初のインスタンスの終了、2番目のインスタンスの終了」を生成します。これは非常に間違っています。報告する必要があります。メモリ消費の問題は別として、これは完全に壊れます
GSerg

1
@GSerg-たまたまこれを報告するチャンネルがありますか?どこに問題を報告するかを理解しようとするほど、私には何も速くは届きません。このサポートページ に例のリード線のため、このサポートページ効果的に何にもつながります。
Lieven Keersmaekers

回答:


1

私には問題を説明する解決策や公式の情報源がないので、賞金の期限が切れるのを待っていました。

バグが修正されるまで役立つ不快な回避策を思いつきました。

回避策は、ローカル変数を使用して、を介して実行される可能性のあるプロシージャのオブジェクトインスタンスを保持しないことGetRefです。

暗黙的または明示的な変数の代わりに、ローカル(または再帰がない場合はグローバル)辞書オブジェクトを使用してオブジェクトインスタンスを保持し、その辞書を介してそれらを呼び出します。

Sub CreateDestroyTwoInstances
  Dim Refs
  Set Refs = CreateObject("Scripting.Dictionary")
  Name = "First Instance"
  Refs.Add "DummyInstance", New IDummyInstance
  ' Call Refs("DummyInstance").DoSomething()
  Refs.Remove "DummyInstance"
  Name = "Second Instance"
  Refs.Add "DummyInstance", New IDummyInstance
  ' Call Refs("DummyInstance").DoSomething()
  Refs.Remove "DummyInstance"
End Sub

複雑すぎないスクリプトがある場合は、使用する価値があるようです。


1
ちょうどそれをテストし、私はそれが私のマシンで動作することを確認できます。これを解決策としてマークします。マイクロソフトはこの修正を提供するまで、それはまだ最高だ(彼らはバグであること、これを認めると仮定し)
Lieven Keersmaekers
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.