KB4525236으로 GetRef의 메모리 소비 (가비지 수집)가 변경되었습니다.


11

Windows 2016 서버 / Windows 10 클라이언트에 KB4525236 을 설치 한 후 메모리 부족 문제가 발생 합니다. 이 보안 수정 프로그램은를 통해 함수를 호출 할 때 메모리가 가비지 수집되는 순간을 변경 한 것으로 보입니다 GetRef.

Pré KB4525236

를 통해 호출 된 함수에서 생성 된 각 인스턴스 GetRef는 인스턴스 변수가nothing

포스트 KB4525236

통해 호출 된 함수에서 작성된 각 인스턴스 GetRef는 메모리에 남아 있으며 전체 함수가 완료 될 때만 가비지 수집됩니다 . 루프에서 인스턴스를 만들 때 특히 32 비트 프로세스에서 빠르게 메모리 부족이 발생하여 메모리 부족이 발생할 수 있습니다.

질문

  • 온라인에서 관련 항목을 찾을 수 없으므로 동일한 문제가 발생하는 다른 사람들로부터 확인을 받고 싶습니다. 스크래치
    편집 : 이것은 같은 문제이지만 아직 해결책이 없습니다
    (KB4524570 (2019 년 11 월 12 일) Windows 10 1903 이후 vbscript.dll class_terminate 버그)
  • 누군가가 실행 가능한 솔루션을 검증하고 알 수 있다면 정말 좋을 것입니다.

POC

KB4525236이 설치된 장치에서 실행되는 다음 스크립트는 가비지 수집의 차이점을 보여줍니다.

  • 직접 호출 : 두 번째 인스턴스는 첫 번째 인스턴스가 파괴 된 후에 만 생성됩니다 (원하는 동작입니다)
  • 호출 됨 GetRef: 첫 번째 인스턴스가 파괴 되기 전에 두 번째 인스턴스가 생성 되므로 메모리를 사용하는 두 개의 인스턴스가 있습니다.

다른 이름으로 저장 : KB4525236.vbs
다음으로 실행 : 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-문제는 생성 된 인스턴스가 끝날 GetRef()때까지 가비지 수집되지 않는다는 것 GetRef()입니다. 그것은 원래의 것과 다릅니다. 우리는 GetRef()1000의 인스턴스 생성을 통해 호출 된 함수를 가지고 GetRef()있으며 과거에는 끝날 때까지 메모리 누적을 유지 하고 루프 인을 실행하는 동안 해제되었습니다 GetRef().
— Lieven Keersmaekers

1
설명해 주셔서 감사합니다. 그 tbh에 대해 무엇을 할 수 있을지 잘 모르겠습니다. 누구나 알고 있다면 VBScript를 만든 원래 팀에서 일하면서 @ eric-lippert가 될 것이라고 상상해보십시오.
— Lankymart

2
KB4525236 또는 KB4524570없이 Windows 7에서 설명하는 동작이 있습니다 (Windows 7에 대해 다른 KB가 있음). 여전히 VBScript에는 가비지 수집이 없으므로 참조 횟수가 0으로 떨어지면 개체 를 삭제해야합니다. 그렇지 않으면 GC 기능의 다른 방식이 아니라 엔진 버그입니다.
— GSerg

2
명시적인 변수가없는 경우에도 마찬가지입니다. 두 With New IDummyInstance : End With블록은 여전히 ​​"첫 번째 인스턴스 초기화, 두 번째 인스턴스 초기화, 첫 번째 인스턴스 종료, 두 번째 인스턴스 종료"를 생성합니다. 이것은 매우 잘못되었으므로보고해야합니다. 별도로 메모리 사용 일로부터 완전히 중단 이 .
— GSerg

1
@GSerg-이 내용을보고 할 채널이 있습니까? 문제를보고 할 위치를 파악하는 것보다 더 빠른 것은 없습니다. 이 지원 페이지 에 예를 리드에 대한 이 지원 페이지 를 효과적으로 아무것도 연결됩니다.
— Lieven Keersmaekers

답변:


1

문제를 설명하는 솔루션이나 공식 소스가 없기 때문에 현상금이 만료되기를 기다리고있었습니다.

버그가 수정 될 때까지 도움이되는 불쾌한 해결 방법이 있습니다.

해결 방법은 로컬 변수를 사용하여 실행할 수있는 프로 시저에서 오브젝트 인스턴스를 보유하지 않는 것 GetRef입니다.

암시 적 또는 명시 적 변수 대신 로컬 (또는 재귀가없는 경우 전역) 사전 개체를 사용하여 개체 인스턴스를 보유하고 해당 사전을 통해 호출합니다.

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

너무 복잡하지 않은 스크립트가 있으면 사용하는 것이 좋습니다.


1
방금 테스트하여 내 컴퓨터에서 작동하는지 확인할 수 있습니다. 이것을 솔루션으로 표시하겠습니다. Microsoft가 수정 사항을 제공 할 때까지는 아직 최고입니다 (버그임을 인정한다고 가정) .
— Lieven Keersmaekers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.