Ocorremos problemas de falta de memória após a instalação do KB4525236 em nossos servidores Windows 2016 / Windows 10 Clients. Essa correção de segurança parece ter mudado o momento em que a memória é coletada como lixo ao chamar uma função GetRef
.
Pré KB4525236
Cada instância criada em uma função chamada através de GetRef
coleta de lixo foi coletada assim que a variável de instância foi definida comonothing
Mensagem KB4525236
Cada instância criada em uma função chamada através GetRef
permanece na memória e é coletada como lixo somente quando a função inteira é concluída . Ao criar instâncias em um loop, isso pode aumentar rapidamente e levar a uma falta de memória, especialmente em um processo de 32 bits.
Questões
- não conseguimos encontrar nada relevante on-line, portanto, gostaríamos de receber confirmação de outras pessoas com o mesmo problema.
EDIT arranha isso: esse é o mesmo problema, mas ainda não há solução
(bug vbscript.dll class_terminate desde KB4524570 (12 de novembro de 2019) Windows 10 1903) - se alguém puder verificar e conhecer uma solução viável, isso seria incrível.
POC
O script a seguir em execução em um dispositivo com o KB4525236 instalado mostra a diferença na coleta de lixo quando
- chamado diretamente: a segunda instância é criada somente após a destruição da primeira instância (esse é o nosso comportamento desejado)
- chamado através
GetRef
: a segunda instância é criada antes que a primeira instância seja destruída, então temos duas instâncias usando memória.
salve como: KB4525236.vbs
execute como: 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
fonte
GetRef()
não recebem lixo coletado até oGetRef()
final. Isso é diferente do que era. Temos funções chamadas através daGetRef()
criação de milhares de instâncias e elas continuam acumulando memória até oGetRef()
fim, enquanto no passado foram liberadas durante a execução do loopGetRef()
.With New IDummyInstance : End With
blocos ainda produzem "Inicializar Primeira Instância, Inicializar Segunda Instância, Terminar Primeira Instância, Terminar Segunda Instância". Isso está muito errado, deve ser relatado. Além da coisa consumo de memória, quebra completamente este .Respostas:
Como não tenho uma solução ou uma fonte oficial que explique o problema, estava esperando a recompensa expirar.
Eu vim com uma solução desagradável que pode ajudar até que o bug seja corrigido.
A solução alternativa é não usar nenhuma variável local para manter instâncias de objeto em procedimentos que possam ser executados
GetRef
.Em vez de variáveis implícitas ou explícitas, o uso de um objeto de dicionário local (ou global, se não houver recursão) para conter instâncias de objetos e chamá-las através desse dicionário funciona.
Parece valer a pena usar se você tiver um script que não seja muito complicado.
fonte