La consommation de mémoire de GetRef (garbage collection) a changé avec KB4525236

11

Nous rencontrons des problèmes de mémoire insuffisante après l'installation de KB4525236 sur nos serveurs Windows 2016 / clients Windows 10. Ce correctif de sécurité semble avoir changé le moment où la mémoire est récupérée lors de l'appel d'une fonction via GetRef.

Pré KB4525236

Chaque instance créée dans une fonction appelée via GetRefrécupère les ordures dès que la variable d'instance est définie surnothing

Message KB4525236

Chaque instance créée dans une fonction appelée via GetRefreste en mémoire et n'est récupérée que lorsque la fonction entière est terminée . Lors de la création d'instances dans une boucle, cela peut rapidement s'accumuler et entraîner une mémoire insuffisante, en particulier dans un processus 32 bits.

Des questions

  • nous ne trouvons rien de pertinent en ligne, nous aimerions donc obtenir la confirmation d'autres personnes rencontrant le même problème.
    EDIT rien que: c'est le même problème , mais sans solution pour l'instant (bug vbscript.dll Class_Terminate depuis KB4524570 (12 Novembre, 2019) de Windows 10 1903)
  • si quelqu'un peut vérifier et connaît une solution viable, ce serait génial.

POC

Le script suivant exécuté sur un appareil sur lequel KB4525236 est installé montre la différence de collecte des ordures lorsque

  • appelé directement: la deuxième instance n'est créée qu'après la destruction de la première instance (c'est notre comportement souhaité)
  • appelé à travers GetRef: la deuxième instance est créée avant la première instance est détruite donc nous avons deux instances utilisant de la mémoire.

enregistrer sous: KB4525236.vbs
exécuter comme: 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
la source
1
@Lankymart - le problème est que les instances créées dans GetRef()ne sont pas récupérées jusqu'à la GetRef()fin. C'est différent de ce que c'était. Nous avons des fonctions appelées en GetRef()créant des milliers d'instances et elles continuent de cumuler la mémoire jusqu'à la GetRef()fin tandis que dans le passé, elles ont été libérées lors de l'exécution de la boucle GetRef().
Lieven Keersmaekers
1
Merci d'avoir clarifié, je ne suis pas sûr de ce que vous allez pouvoir faire à ce sujet. Imaginez si quelqu'un le sait, ce sera @ eric-lippert alors qu'ils ont travaillé sur l'équipe d'origine qui a construit VBScript.
Lankymart
2
J'ai le comportement que vous décrivez sur Windows 7 sans KB4525236 ou KB4524570 (apparemment, il y a un autre KB qui le fait pour Windows 7). Pourtant, il n'y a pas de récupération de place dans VBScript, les objets doivent être détruits lorsque leur nombre de références tombe à zéro. Si cela ne se produit pas, c'est un bogue de moteur plutôt qu'une autre façon de fonctionner du GC.
GSerg
2
C'est le cas même sans variables explicites. Deux With New IDummyInstance : End Withblocs produisent toujours "Initialize First Instance, Initialize Second Instance, Terminate First Instance, Terminate Second Instance". C'est très faux, il faut le signaler. En dehors de la consommation de mémoire, cela casse complètement cela .
GSerg
1
@GSerg - Avez-vous une chaîne pour signaler cela? Rien ne m'arrive plus rapidement que d'essayer de savoir où signaler les problèmes. Cette page d'assistance par exemple mène à cette page d'assistance qui ne mène à rien.
Lieven Keersmaekers

Réponses:

1

Comme je n'ai pas de solution ou de source officielle expliquant le problème, j'attendais que la prime expire.

J'ai trouvé une solution de contournement désagréable qui peut aider jusqu'à ce que le bug soit corrigé.

La solution de contournement consiste à ne pas utiliser de variable locale pour conserver les instances d'objet dans les procédures qui pourraient être exécutées GetRef.

Au lieu de variables implicites ou explicites, l'utilisation d'un objet de dictionnaire local (ou global s'il n'y a pas de récursivité) pour contenir les instances d'objet et les appeler via ce dictionnaire fonctionne.

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

Cela semble valoir la peine d'être utilisé si vous avez un script qui n'est pas trop compliqué.

Kul-Tigin
la source
1
Je viens de le tester et je peux confirmer qu'il fonctionne sur ma machine. Je vais marquer cela comme la solution. C'est le meilleur encore jusqu'à ce que Microsoft fournisse un correctif (en supposant qu'ils reconnaissent qu'il s'agit d'un bogue) .
Lieven Keersmaekers