Tiêu thụ bộ nhớ của GetRef (bộ sưu tập rác) đã thay đổi với KB4525236


11

Chúng tôi gặp phải sự cố hết bộ nhớ sau khi cài đặt KB4525236 trên Máy chủ Windows 2016 / Máy khách Windows 10 của chúng tôi. Khắc phục bảo mật này dường như đã thay đổi thời điểm bộ nhớ bị thu gom rác khi gọi hàm thông quaGetRef .

Pré KB4525236

Mỗi phiên bản được tạo trong một hàm được gọi thông qua GetRefđã thu thập rác ngay khi biến thể hiện được đặt thànhnothing

Bài KB4525236

Mỗi phiên bản được tạo trong một hàm được gọi thông qua GetRefvẫn còn trong bộ nhớ và chỉ được thu gom rác khi toàn bộ chức năng hoàn thành . Khi tạo các thể hiện trong một vòng lặp, điều này có thể nhanh chóng bổ sung và dẫn đến tình trạng hết bộ nhớ, đặc biệt là trong quy trình 32 bit.

Câu hỏi

  • chúng tôi không thể tìm thấy bất cứ điều gì có liên quan trực tuyến vì vậy chúng tôi muốn nhận được xác nhận từ những người khác gặp vấn đề tương tự.
    EDIT cào rằng: đây là vấn đề tương tự nhưng chưa có giải pháp nào
    (lỗi vbscript.dll class_terminate kể từ KB4524570 (ngày 12 tháng 11 năm 2019) Windows 10 1903)
  • nếu bất cứ ai có thể xác minh và biết một giải pháp khả thi, điều đó sẽ thật tuyệt vời.

POC

tập lệnh sau chạy trên thiết bị có cài đặt KB4525236 cho thấy sự khác biệt trong thu gom rác khi

  • được gọi trực tiếp: thể hiện thứ hai chỉ được tạo sau khi cá thể thứ nhất bị hủy (đây là hành vi mong muốn của chúng tôi)
  • được gọi qua GetRef: thể hiện thứ hai được tạo trước khi cá thể thứ nhất bị hủy để chúng có hai thể hiện sử dụng bộ nhớ.

lưu dưới dạng: KB4525236.vbs
chạy dưới dạng: 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 - vấn đề là các trường hợp được tạo trong GetRef()không được thu gom rác cho đến khi GetRef()kết thúc. Điều đó khác với những gì nó đã được. Chúng ta có các hàm được gọi thông qua GetRef()việc tạo ra 1000 trường hợp và chúng tiếp tục tích lũy bộ nhớ cho đến khi GetRef()kết thúc trong quá khứ, chúng được giải phóng trong khi thực hiện vòng lặp GetRef().
Lieven Keersmaekers

1
Cảm ơn đã làm rõ, tôi không chắc bạn sẽ làm gì về điều đó. Hãy tưởng tượng nếu có ai biết, đó sẽ là @ eric-lippert khi họ làm việc với nhóm ban đầu đã xây dựng VBScript.
Lankymart

2
Tôi có hành vi mà bạn mô tả trên Windows 7 mà không có KB4525236 hoặc KB4524570 (rõ ràng có một KB khác thực hiện với Windows 7). Tuy nhiên, VBScript không có bộ sưu tập rác, các đối tượng phải bị hủy khi số tham chiếu của chúng giảm xuống không. Nếu điều đó không xảy ra, đó là một lỗi động cơ chứ không phải là một cách hoạt động khác của GC.
GSerg

2
Đây là trường hợp ngay cả khi không có biến rõ ràng. Hai With New IDummyInstance : End Withkhối vẫn tạo ra "Khởi tạo sơ thẩm, khởi tạo sơ thẩm thứ hai, chấm dứt sơ thẩm, chấm dứt sơ thẩm thứ hai". Điều này là rất sai, nó cần được báo cáo. Ngoài việc tiêu thụ bộ nhớ, nó hoàn toàn phá vỡ điều này .
GSerg

1
@GSerg - Bạn có tình cờ có một kênh để báo cáo điều này không? Không có gì giúp tôi nhanh hơn là cố gắng tìm ra nơi để báo cáo vấn đề. Ví dụ, trang hỗ trợ này dẫn đến trang hỗ trợ này dẫn đến hiệu quả không có gì.
Lieven Keersmaekers

Câu trả lời:


1

Vì tôi không có giải pháp hoặc nguồn chính thức nào giải thích vấn đề nên tôi đang chờ tiền thưởng hết hạn.

Tôi đã đưa ra một cách giải quyết khó chịu có thể giúp cho đến khi sửa lỗi.

Cách giải quyết là không sử dụng bất kỳ biến cục bộ nào để giữ các thể hiện đối tượng trong các thủ tục có thể được thực thi thông qua GetRef .

Thay vì các biến ẩn hoặc rõ ràng, sử dụng một đối tượng từ điển cục bộ (hoặc toàn cầu nếu không có đệ quy) để giữ các thể hiện đối tượng và gọi chúng thông qua từ điển đó hoạt động.

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

Nó có vẻ đáng sử dụng nếu bạn có một kịch bản không quá phức tạp.


1
Chỉ cần thử nghiệm nó và tôi có thể xác nhận nó hoạt động trên máy của tôi. Tôi sẽ đánh dấu đây là giải pháp. Đây là cách tốt nhất cho đến khi Microsoft cung cấp bản sửa lỗi (giả sử họ thừa nhận đây là lỗi) .
Lieven Keersmaekers
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.