【发布时间】:2020-02-06 07:28:05
【问题描述】:
在我们的 Windows 2016 服务器/Windows 10 客户端上安装 KB4525236 后,我们遇到了内存不足的问题。这个安全修复似乎改变了通过GetRef调用函数时内存被垃圾收集的时刻。
前 KB4525236
在通过GetRef 调用的函数中创建的每个实例都会在实例变量设置为nothing 后立即被垃圾回收
发布 KB4525236
在通过GetRef 调用的函数中创建的每个实例都保留在内存中,并且只有在整个函数完成时才会收集垃圾。在循环中创建实例时,这会很快累加并导致内存不足,尤其是在 32 位进程中。
问题
- 我们在网上找不到任何相关内容,因此我们希望得到其他遇到相同问题的人的确认。
编辑划掉:this 是同样的问题,但没有解决方案尚未
(自 KB4524570(2019 年 11 月 12 日)Windows 10 1903 以来的 vbscript.dll class_terminate 错误) - 如果有人能够验证并知道可行的解决方案,那就太棒了。
POC
在安装了 KB4525236 的设备上运行的以下脚本显示了垃圾收集的差异
- 直接调用:第二个实例仅在第一个实例被销毁后创建(这是我们想要的行为)
- 通过
GetRef调用:第二个实例被创建之前第一个实例被销毁,因此有两个实例使用内存。
另存为: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
【问题讨论】:
-
@Lankymart - 问题是在
GetRef()中创建的实例在GetRef()结束之前不会被垃圾收集。那和原来的不一样。我们有通过GetRef()调用的函数创建 1000 个实例,它们会不断累积内存,直到GetRef()结束,而在过去,它们在GetRef()中执行循环时被释放。 -
感谢您的澄清,我不确定您将能够对此做些什么。想象一下,如果有人知道,那将是 @eric-lippert,因为他们在构建 VBScript 的原始团队中工作。
-
我有你在没有 KB4525236 或 KB4524570 的 Windows 7 上描述的行为(显然还有另一个 KB 对 Windows 7 执行此操作)。尽管如此,VBScript 中没有垃圾回收,当对象must 的引用计数降至零时将被销毁。如果这没有发生,那就是引擎错误,而不是 GC 运行的不同方式。
-
即使没有显式变量也是如此。两个
With New IDummyInstance : End With块仍然产生“初始化第一个实例,初始化第二个实例,终止第一个实例,终止第二个实例”。这是非常错误的,应该举报。除了内存消耗之外,它完全打破了this。 -
@Gserg - 谢谢。至少,this 让我开心;)
标签: memory-management vbscript null garbage-collection reference-type