El consumo de memoria de GetRef (recolección de basura) cambió con KB4525236

11

Experimentamos problemas de falta de memoria después de instalar KB4525236 en nuestros servidores Windows 2016 / Clientes Windows 10. Esta solución de seguridad parece haber cambiado en el momento en que se recolecta basura en la memoria cuando se llama a una función GetRef.

Pré KB4525236

Cada instancia creada en una función llamada GetRefse recogió basura tan pronto como la variable de instancia se estableció ennothing

Publicar KB4525236

Cada instancia creada en una función llamada a través GetRefpermanece en la memoria y se recolecta basura solo cuando se completa toda la función . Al crear instancias en un bucle, esto puede sumar rápidamente y conducir a una falta de memoria, especialmente en un proceso de 32 bits.

Preguntas

  • no podemos encontrar nada relevante en línea, por lo que nos gustaría obtener la confirmación de otras personas que experimentan el mismo problema.
    EDITAR tachar eso: este es el mismo problema pero aún no tiene solución
    (error vbscript.dll class_terminate desde KB4524570 (12 de noviembre de 2019) Windows 10 1903)
  • si alguien puede verificar y conoce una solución viable, sería genial.

POC

El siguiente script que se ejecuta en un dispositivo con KB4525236 instalado muestra la diferencia en la recolección de basura cuando

  • llamado directamente: la segunda instancia se crea solo después de que se destruye la primera instancia (este es nuestro comportamiento deseado)
  • llamado GetRef: la segunda instancia se crea antes de que se destruya la primera instancia, por lo que hay dos instancias que usan memoria.

guardar como: KB4525236.vbs
ejecutar como: 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
Lieven Keersmaekers
fuente
1
@Lankymart: el problema es que las instancias creadas en GetRef()no se recolectan hasta que GetRef()finaliza. Eso es diferente a lo que era. Tenemos funciones llamadas a través de la GetRef()creación de miles de instancias y siguen acumulando memoria hasta el GetRef()final, mientras que en el pasado, se liberaron al ejecutar el bucle GetRef().
Lieven Keersmaekers
1
Gracias por aclarar, no estoy seguro de lo que van a poder hacer al respecto. Imagínese si alguien lo sabe, será @ eric-lippert mientras trabajaban en el equipo original que creó VBScript.
Lankymart
2
Tengo el comportamiento que describe en Windows 7 sin KB4525236 o KB4524570 (aparentemente hay otro KB que lo hace en Windows 7). Aún así, no hay recolección de basura en VBScript, los objetos deben destruirse cuando su recuento de referencia cae a cero. Si eso no sucede, es un error del motor en lugar de una forma diferente de funcionamiento del GC.
GSerg
2
Este es el caso incluso sin variables explícitas. Dos With New IDummyInstance : End Withbloques aún producen "Inicializar primera instancia, Inicializar segunda instancia, Terminar primera instancia, Terminar segunda instancia". Esto está muy mal, debe informarse. Aparte del consumo de memoria, rompe completamente esto .
GSerg
1
@GSerg - ¿Tienes un canal para reportar esto? Nada me llega más rápido que tratar de averiguar dónde informar problemas. Esta página de soporte, por ejemplo, lleva a esta página de soporte que efectivamente no lleva a nada.
Lieven Keersmaekers

Respuestas:

1

Como no tengo una solución o una fuente oficial que explique el problema, estaba esperando que expirara la recompensa.

Se me ocurrió una solución desagradable que puede ayudar hasta que se solucione el error.

La solución alternativa es no utilizar ninguna variable local para contener instancias de objetos en procedimientos que podrían ejecutarse a través de GetRef .

En lugar de variables implícitas o explícitas, usar un objeto de diccionario local (o global si no hay recursividad) para contener instancias de objetos y llamarlas a través de ese diccionario funciona.

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

Parece que vale la pena usarlo si tiene un script que no es demasiado complicado.

Kul-Tigin
fuente
1
Solo lo probé y puedo confirmar que funciona en mi máquina. Voy a marcar esto como la solución. Es lo mejor hasta que Microsoft proporcione una solución (suponiendo que reconozcan que se trata de un error) .
Lieven Keersmaekers