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.