Споживання пам'яті GetRef (збирання сміття) змінилося на KB4525236


11

У нас виникають проблеми із пам'яттю після встановлення KB4525236 на наших серверах Windows 2016 / Клієнтах Windows 10. Це виправлення безпеки, схоже, змінило момент, коли пам'ять збирається сміттям під час виклику функції через GetRef.

Pré KB4525236

Кожен екземпляр, створений у функції, яка викликається через GetRefзібране сміття, як тільки було встановлено змінну екземпляраnothing

Повідомлення KB4525236

Кожен екземпляр, створений у функції, викликаної наскрізь, GetRefзалишається в пам'яті і збирається сміття лише тоді, коли вся функція завершена . Створюючи екземпляри в циклі, це може швидко скласти і призвести до втрати пам’яті, особливо в 32-бітному процесі.

Запитання

  • ми не можемо знайти нічого релевантного в Інтернеті, тому ми хотіли б отримати підтвердження від інших, які відчувають ту саму проблему.
    EDIT подряпини: це та сама проблема, але поки немає рішення
    (помилка 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()створення 1000 екземплярів, і вони зберігають накопичувальну пам'ять до GetRef()кінців, а в минулому вони були звільнені під час виконання циклу GetRef().
Лівен Кірсмейкер

1
Дякую за уточнення, я не впевнений, що ви зможете зробити з цього приводу. Уявіть, якщо хтось знає, це буде @ eric-lippert, коли вони працювали над оригінальною командою, яка побудувала VBScript.
Ланкімарт

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 не виправить (припускаючи, що вони визнають це помилкою) .
Лівен Кірсмейкерс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.