У нас возникают проблемы с нехваткой памяти после установки KB4525236 на наших серверах Windows 2016 / Windows 10 Clients. Это исправление безопасности, похоже, изменило момент, когда память собирает мусор при вызове функции GetRef
.
Pr KB4525236
Каждый экземпляр, созданный в функции, вызванной с помощью GetRef
метода «мусор», собирается как только переменная экземпляра была установленаnothing
Пост KB4525236
Каждый экземпляр, созданный в вызываемой функции, GetRef
остается в памяти и удаляется только после завершения всей функции . При создании экземпляров в цикле это может быстро сложиться и привести к нехватке памяти, особенно в 32-разрядном процессе.
Вопросов
- мы не можем найти что-либо релевантное в Интернете, поэтому мы хотели бы получить подтверждение от других людей, столкнувшихся с такой же проблемой.
РЕДАКТИРУЙТЕ это: это та же проблема, но пока нет решения
(ошибка vbscript.dll в class_terminate начиная с KB4524570 (12 ноября 2019 г.) Windows 10 1903) - если кто-то может проверить и знает работоспособное решение, это было бы здорово.
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
источник
GetRef()
не собирают мусор доGetRef()
конца. Это отличается от того, что было. У нас есть функции, вызываемые путемGetRef()
создания тысяч экземпляров, и они продолжают накапливать память доGetRef()
конца, пока в прошлом они не освобождались при выполнении циклаGetRef()
.With New IDummyInstance : End With
блока по-прежнему выдают «Инициализация первого экземпляра, Инициализация второго экземпляра, Завершение первого экземпляра, Завершение второго экземпляра». Это очень неправильно, это должно быть сообщено. Помимо потребления памяти, это полностью ломает это .Ответы:
Поскольку у меня нет решения или официального источника, объясняющего проблему, я ждал истечения срока действия награды.
Я нашел неприятный обходной путь, который может помочь, пока ошибка не будет устранена.
Обходной путь не должен использовать какую-либо локальную переменную для хранения экземпляров объекта в процедурах, которые могут быть выполнены через
GetRef
.Вместо неявных или явных переменных использование локального (или глобального, если нет рекурсии) объекта словаря для хранения экземпляров объекта и вызова их через этот словарь работает.
Кажется, стоит использовать, если у вас есть скрипт, который не слишком сложен.
источник