Il consumo di memoria di GetRef (garbage collection) è stato modificato con KB4525236


11

Si verificano problemi di memoria insufficiente dopo l'installazione di KB4525236 sui nostri server Windows 2016 / client Windows 10. Questa correzione di sicurezza sembra aver cambiato il momento in cui la memoria viene raccolta in modo inutile quando si chiama una funzione GetRef.

Pré KB4525236

Ogni istanza creata in una funzione chiamata tramite ha GetRefottenuto la garbage collection non appena è stata impostata la variabile di istanzanothing

Posta KB4525236

Ogni istanza creata in una funzione chiamata through GetRefrimane in memoria ed è garbage collection solo al completamento dell'intera funzione . Quando si creano istanze in un ciclo, ciò può sommarsi rapidamente e portare a memoria insufficiente, specialmente in un processo a 32 bit.

Domande

  • non riusciamo a trovare nulla di rilevante online, quindi vorremmo ottenere la conferma da altri che riscontrano lo stesso problema.
    MODIFICA che: questo è lo stesso problema ma ancora senza soluzione
    (bug class_terminate vbscript.dll dal KB4524570 (12 novembre 2019) Windows 10 1903)
  • se qualcuno può verificare e conoscere una soluzione praticabile, sarebbe fantastico.

POC

lo script seguente in esecuzione su un dispositivo con KB4525236 installato mostra la differenza nella raccolta dei rifiuti quando

  • chiamato direttamente: la seconda istanza viene creata solo dopo la distruzione della prima istanza (questo è il comportamento desiderato)
  • chiamato attraverso GetRef: la seconda istanza viene creata prima che la prima istanza venga distrutta, quindi abbiamo due istanze che usano la memoria.

salva come: KB4525236.vbs
eseguito come: 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 - il problema è che le istanze create GetRef()non ricevono la spazzatura fino alla GetRef()fine. È diverso da quello che era. Abbiamo funzioni richiamate attraverso la GetRef()creazione di migliaia di istanze e continuano a accumulare memoria fino alla GetRef()fine mentre in passato venivano liberate durante l'esecuzione del loop GetRef().
Lieven Keersmaekers,

1
Grazie per il chiarimento, non sono sicuro di cosa sarai in grado di fare a riguardo. Immagina se qualcuno lo sapesse, sarà @ eric-lippert mentre lavoravano al team originale che ha creato VBScript.
Lankymart,

2
Ho il comportamento che descrivi su Windows 7 senza KB4525236 o KB4524570 (apparentemente c'è un altro KB che lo fa su Windows 7). Tuttavia, non esiste una garbage collection in VBScript, gli oggetti devono essere distrutti quando il loro conteggio dei riferimenti scende a zero. Se ciò non accade, si tratta di un bug del motore piuttosto che di un modo diverso di funzionare con GC.
GSerg

2
Questo è il caso anche senza variabili esplicite. Due With New IDummyInstance : End Withblocchi producono ancora "Inizializza prima istanza, inizializza seconda istanza, termina prima istanza, termina seconda istanza". Questo è molto sbagliato, dovrebbe essere segnalato. A parte la cosa consumo di memoria, si rompe completamente questo .
GSerg

1
@GSerg - Hai un canale per segnalarlo? Niente mi arriva più veloce del cercare di capire dove segnalare i problemi. Questa pagina di supporto, ad esempio, porta a questa pagina di supporto che in realtà non porta a nulla.
Lieven Keersmaekers,

Risposte:


1

Dal momento che non ho una soluzione o una fonte ufficiale che spieghi il problema, stavo aspettando che la grazia scadesse.

Ho escogitato una soluzione spiacevole che può aiutare fino a quando il bug non viene risolto.

Per risolvere il problema, non utilizzare alcuna variabile locale per contenere istanze di oggetti in procedure che potrebbero essere eseguite GetRef.

Invece di variabili implicite o esplicite, usare un oggetto dizionario locale (o globale se non c'è ricorsione) per contenere istanze di oggetti e chiamarle attraverso quel dizionario funziona.

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

Sembra che valga la pena usarlo se hai uno script non troppo complicato.


1
Ho appena provato e posso confermare che funziona sulla mia macchina. Lo segnerò come soluzione. È il migliore fino a quando Microsoft non fornisce una correzione (supponendo che riconoscano che si tratta di un bug) .
Lieven Keersmaekers,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.