Потребление памяти GetRef (сборка мусора) изменилось с помощью KB4525236

11

У нас возникают проблемы с нехваткой памяти после установки 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
Ливен Керсмакерс
источник
1
@Lankymart - проблема в том, что созданные экземпляры GetRef()не собирают мусор до GetRef()конца. Это отличается от того, что было. У нас есть функции, вызываемые путем GetRef()создания тысяч экземпляров, и они продолжают накапливать память до GetRef()конца, пока в прошлом они не освобождались при выполнении цикла GetRef().
Ливен Керсмакерс
1
Спасибо за разъяснение, я не уверен, что вы сможете сделать с этим тбн. Представьте, что если кто-то знает, это будет @ eric-lippert, так как они работали над оригинальной командой, которая создавала VBScript.
Lankymart
2
У меня есть поведение, которое вы описываете в Windows 7 без KB4525236 или KB4524570 (очевидно, есть еще один КБ, который делает это с Windows 7). Тем не менее, в VBScript нет сборки мусора, объекты должны быть уничтожены, когда их число ссылок падает до нуля. Если этого не происходит, то это ошибка двигателя, а не другой способ работы GC.
GSerg
2
Это имеет место даже без явных переменных. Два With New IDummyInstance : End Withблока по-прежнему выдают «Инициализация первого экземпляра, Инициализация второго экземпляра, Завершение первого экземпляра, Завершение второго экземпляра». Это очень неправильно, это должно быть сообщено. Помимо потребления памяти, это полностью ломает это .
GSerg
1
@GSerg - У вас есть канал, чтобы сообщить об этом? Ничто не добирается до меня быстрее, чем пытаться понять, где сообщать о проблемах. Эта страница поддержки, например, ведет к этой странице поддержки, которая фактически ни к чему не приводит.
Ливен Керсмакерс

Ответы:

1

Поскольку у меня нет решения или официального источника, объясняющего проблему, я ждал истечения срока действия награды.

Я нашел неприятный обходной путь, который может помочь, пока ошибка не будет устранена.

Обходной путь не должен использовать какую-либо локальную переменную для хранения экземпляров объекта в процедурах, которые могут быть выполнены через GetRef.

Вместо неявных или явных переменных использование локального (или глобального, если нет рекурсии) объекта словаря для хранения экземпляров объекта и вызова их через этот словарь работает.

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

Кажется, стоит использовать, если у вас есть скрипт, который не слишком сложен.

Кул-ТИГИН
источник
1
Только что проверил, и я могу подтвердить, что он работает на моей машине. Я собираюсь отметить это как решение. Это лучшее, пока Microsoft не предоставит исправление (если они признают, что это ошибка) .
Ливен Керсмакерс