问题
We experience out-of-memory issues after installing KB4525236 on our Windows 2016 Servers/Windows 10 Clients. This security fix seems to have changed the moment when memory is garbage collected when calling a function through GetRef
.
Pré KB4525236
Each instance created in a function called through GetRef
got garbage collected as soon as the instance variable was set to nothing
Post KB4525236
Each instance created in a function called through GetRef
remains in memory and is garbage collected only when the entire function completes. When creating instances in a loop, this can quickly add up and lead to an out-of-memory, especially in a 32-bit process.
Questions
- we can not find anything relevant online so we would like to get confirmation from others experiencing the same issue.
EDIT scratch that: this is the same issue but with no solution as of yet
(vbscript.dll class_terminate bug since KB4524570 (November 12, 2019) Windows 10 1903) - if anyone can verify and knows a workable solution, that would be awesome.
POC
following script running on a device with KB4525236 installed shows the difference in garbage collecting when
- called directly: the second instance gets created only after the first instance is destroyed (this is our desired behavior)
- called through
GetRef
: the second instance gets created before the first instance is destroyed so whe have two instances using memory.
save as: KB4525236.vbs
run as: 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:
Since I don't have a solution or an official source explaining the issue I was waiting the bounty to expire.
I've come up with an unpleasant workaround that can help until the bug is fixed.
The workaround is not to use any local variable to hold object instances in procedures that might be executed through GetRef
.
Instead of implicit or explicit variables, using a local (or global if there's no recursion) dictionary object to hold object instances and calling them through that dictionary works.
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
It seems to be worth using if you have a script that is not too complicated.
来源:https://stackoverflow.com/questions/60089691/getrefs-memory-consumption-garbage-collection-changed-with-kb4525236