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
.
Each instance created in a function called through GetRef
got garbage collected as soon as the instance variable was set to nothing
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.
following script running on a device with KB4525236 installed shows the difference in garbage collecting when
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
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.
Great question. I came to it via a Microsoft forums post
https://answers.microsoft.com/en-us/windows/forum/all/vbscriptdll-classterminate-bug-since-kb4524570/1b34d9b4-91ce-4d61-a05c-1bfa0ec96344?auth=1
The asker of this SO had added a link to it to that above Microsoft thread.
That Microsoft thread was referenced in the release notes for KB5005101 (for Windows 10 21H1 - there will be similar KBs for other Windows 10 versions). Link to the Microsoft release notes: https://support.microsoft.com/en-us/topic/september-1-2021-kb5005101-os-builds-19041-1202-19042-1202-and-19043-1202-preview-82a50f27-a56f-4212-96ce-1554e8058dc1
Microsoft claim to have fixed this issue
Addresses a memory leak that occurs when you use nested classes within VBScript.
In the release notes, the VBScript
word on the end is a hyperlink to that Microsoft forum thread. Rather subtle...
Anyway, whilst I'm not a frequent user of VBScript, as a long-time COM user, and interested reader of this sort of issue anyway, I thought I'd share what should eventually be the definitive answer once everyone gets their monthly patches. Those release notes only go back to Windows 10 2004, so 1909 and earlier may be out of luck, as may Windows 7 users affected by this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With