GetRef'in bellek tüketimi (çöp toplama) KB4525236 ile değişti


11

Windows 2016 Sunucularımıza / Windows 10 İstemcilerimize KB4525236'yı yükledikten sonra bellek yetersizliği sorunları yaşıyoruz . Bu güvenlik düzeltmesi, bir işlevi çağırırken belleğin çöp toplandığı anı değiştirmiş gibi görünüyor GetRef.

Pré KB4525236

Üzerinden çağrılan bir işlevde oluşturulan her örnek GetRef, örnek değişkeni olarak ayarlanır ayarlanmaz çöp toplanırnothing

Post KB4525236

Üzerinden çağrılan bir işlevde oluşturulan her örnek GetRefbellekte kalır ve yalnızca tüm işlev tamamlandığında toplanan çöptür . Bir döngüde örnekler oluştururken, bu, özellikle 32 bit işlemde hızlı bir şekilde bellek yetersiz kalmasına neden olabilir.

Sorular

  • çevrimiçi olarak alakalı bir şey bulamıyoruz, bu yüzden aynı sorunu yaşayan başkalarından onay almak istiyoruz.
    EDIT çizik: Bu aynı sorun ama henüz hiçbir çözüm ile
    (KB4524570 (12 Kasım 2019) Windows 10 1903 beri vbscript.dll class_terminate hata)
  • Herkes çalışabilir bir çözümü doğrulayabilir ve bilirse, bu harika olurdu.

POC

KB4525236 yüklü bir aygıtta çalışan aşağıdaki komut dosyası, çöp toplamadaki farkları

  • doğrudan çağrılır: ikinci örnek yalnızca ilk örnek yok edildikten sonra oluşturulur (bu bizim istenen davranışımızdır)
  • üzerinden çağrılır GetRef: ikinci örnek , ilk örnek yok edilmeden önce oluşturulur , böylece bellek kullanan iki örnek olur.

farklı kaydet: KB4525236.vbs şu şekilde çalıştır : 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 - sorun yaratılan örneklerin GetRef()sonuna kadar çöp toplanmamasıdır GetRef(). Ne olduğundan farklı. GetRef()1000 örnekleri oluşturarak çağrıldığımız işlevler var GetRef()ve geçmişte iken sonuna kadar bellek biriktirmeye devam ediyorlar, döngüyü yürütürken serbest bırakıldılar GetRef().
Lieven Keersmaekers

1
Açıkladığınız için teşekkürler, bu tbh hakkında ne yapabileceğinizden emin değilim. Birisi bilirse, VBScript'i inşa eden orijinal ekip üzerinde çalıştıkça @ eric-lippert olacağını hayal edin.
Lankymart

2
KB4525236 veya KB4524570 olmadan Windows 7'de tanımladığınız davranış var (görünüşe göre Windows 7'ye yapan başka bir KB var). Yine de, VBScript'te çöp toplama yoktur , referans sayısı sıfıra düştüğünde nesneler imha edilmelidir . Bu olmazsa, GC'nin farklı bir şekilde çalışmasından ziyade bir motor hatasıdır.
GSerg

2
Açık değişkenler olmasa bile bu durum söz konusudur. İki With New IDummyInstance : End Withblok hala "İlk Örneği Başlat, İkinci Örneği Başlat, İlk Örneği Sonlandır, İkinci Örneği Sonlandır" üretir. Bu çok yanlış, rapor edilmelidir. Apart bellek tüketimi şeyden, tamamen kırar bu .
GSerg

1
@GSerg - Bunu bildirmek için bir kanalınız var mı? Sorunları nerede bildireceğimizi anlamaya çalışmaktan daha hızlı bir şey elde edemezsiniz. Bu destek sayfası için örnek potansiyel müşteri için bu destek sayfasına etkili bir şey yol açar.
Lieven Keersmaekers

Yanıtlar:


1

Sorunu açıklayan bir çözümüm veya resmi bir kaynağım olmadığından, ödülün süresinin dolmasını bekliyordum.

Hata giderilene kadar yardımcı olabilecek hoş olmayan bir geçici çözüm buldum.

Geçici çözüm, yürütülebilecek yordamlarda nesne örneklerini tutmak için herhangi bir yerel değişken kullanmamaktır GetRef.

Örtük veya açık değişkenler yerine, nesne örneklerini tutmak için yerel (veya özyineleme yoksa global) bir sözlük nesnesi kullanmak ve bu sözlük aracılığıyla bunları çağırmak çalışır.

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

Çok karmaşık olmayan bir komut dosyanız varsa kullanmaya değer gibi görünüyor.


1
Sadece test ettim ve makinemde çalıştığını onaylayabilirim. Bunu çözüm olarak işaretleyeceğim. Microsoft bir düzeltme sağlayana kadar en iyisi (bunun bir hata olduğunu kabul ettikleri varsayılarak) .
Lieven Keersmaekers
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.