Konsumsi memori GetRef (pengumpulan sampah) berubah dengan KB4525236

11

Kami mengalami masalah kehabisan memori setelah menginstal KB4525236 pada Klien Windows 2016 Server / Windows 10 kami. Perbaikan keamanan ini tampaknya telah mengubah saat ketika memori dikumpulkan ketika memanggil suatu fungsi GetRef.

Pra KB4525236

Setiap instance dibuat dalam fungsi yang dipanggil melalui GetRefsampah yang dikumpulkan segera setelah variabel instance diatur kenothing

Poskan KB4525236

Setiap instance dibuat dalam fungsi yang dipanggil GetReftetap dalam memori dan sampah dikumpulkan hanya ketika seluruh fungsi selesai . Saat membuat instance dalam satu loop, ini dapat dengan cepat bertambah dan menyebabkan kehabisan memori, terutama dalam proses 32-bit.

Pertanyaan

  • kami tidak dapat menemukan sesuatu yang relevan secara online sehingga kami ingin mendapatkan konfirmasi dari orang lain yang mengalami masalah yang sama.
    EDIT menggaruk bahwa: ini adalah masalah yang sama tetapi belum ada solusi
    (bug class_terminate vbscript.dll sejak KB4524570 (12 November 2019) Windows 10 1903)
  • jika ada yang bisa memverifikasi dan mengetahui solusi yang bisa diterapkan, itu akan luar biasa.

POC

skrip berikut berjalan pada perangkat dengan KB4525236 diinstal menunjukkan perbedaan dalam pengumpulan sampah saat

  • dipanggil langsung: instance kedua dibuat hanya setelah instance pertama dihancurkan (ini adalah perilaku yang kita inginkan)
  • dipanggil melalui GetRef: instance kedua akan dibuat sebelum instance pertama dihancurkan sehingga ia memiliki dua instance menggunakan memori.

simpan sebagai: KB4525236.vbs
dijalankan sebagai: 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
Letnan Keersmaekers
sumber
1
@Lankymart - masalahnya adalah instans yang dibuat GetRef()tidak mengumpulkan sampah sampai GetRef()selesai. Itu berbeda dengan apa itu. Kami memiliki fungsi yang dipanggil melalui GetRef()pembuatan 1000 instance dan tetap menyimpan memori hingga GetRef()berakhir sementara di masa lalu, mereka dibebaskan saat menjalankan loop GetRef().
Lieven Keersmaekers
1
Terima kasih telah mengklarifikasi, saya tidak yakin apa yang dapat Anda lakukan tentang tbh itu. Bayangkan jika ada yang tahu, itu akan menjadi @ eric-lippert saat mereka bekerja pada tim asli yang membangun VBScript.
Lankymart
2
Saya memiliki perilaku yang Anda jelaskan pada Windows 7 tanpa KB4525236 atau KB4524570 (ternyata ada KB lain yang melakukannya untuk Windows 7). Namun, tidak ada pengumpulan sampah di VBScript, objek harus dihancurkan ketika jumlah referensi turun menjadi nol. Jika itu tidak terjadi, itu adalah bug mesin dan bukan dengan cara fungsi GC yang berbeda.
GSerg
2
Ini adalah kasus bahkan tanpa variabel eksplisit. Dua With New IDummyInstance : End Withblok masih menghasilkan "Inisialisasi Instance Pertama, Inisialisasi Instance Kedua, Hentikan Instance Pertama, Hentikan Instance Kedua". Ini sangat salah, harus dilaporkan. Terlepas dari konsumsi memori, itu benar-benar merusak ini .
GSerg
1
@ GSerg - Apakah Anda memiliki saluran untuk melaporkan ini? Tidak ada yang membuat saya lebih cepat daripada mencoba mencari tahu di mana harus melaporkan masalah. Halaman dukungan ini misalnya mengarah ke halaman dukungan ini yang secara efektif tidak menghasilkan apa-apa.
Lieven Keersmaekers

Jawaban:

1

Karena saya tidak punya solusi atau sumber resmi yang menjelaskan masalah ini, saya sedang menunggu hadiah berakhir.

Saya telah menemukan solusi yang tidak menyenangkan yang dapat membantu sampai bug diperbaiki.

Solusinya adalah tidak menggunakan variabel lokal untuk menyimpan instance objek dalam prosedur yang dapat dieksekusi melalui GetRef.

Alih-alih variabel implisit atau eksplisit, menggunakan objek kamus lokal (atau global jika tidak ada rekursi) untuk menyimpan instance objek dan memanggil mereka melalui kamus tersebut berfungsi.

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

Tampaknya layak digunakan jika Anda memiliki skrip yang tidak terlalu rumit.

Kul-Tigin
sumber
1
Baru saja mengujinya dan saya dapat mengonfirmasi itu berfungsi pada mesin saya. Saya akan menandai ini sebagai solusinya. Ini yang terbaik sampai Microsoft memberikan perbaikan (dengan asumsi mereka mengakui ini bug) .
Lieven Keersmaekers