2013-05-08 40 views
5

Điều gì sẽ xảy ra nếu tôi chuyển một thành viên dữ liệu bằng cách tham chiếu đến một hàm, và trong khi chức năng đó đang chạy, Garbage Collector bắt đầu chạy và di chuyển đối tượng chứa thành viên dữ liệu trong bộ nhớ?truyền dữ liệu thành viên bằng cách tham khảo

class SomeClass 
{ 
    int someDataMember; 

    void someMethod() 
    { 
     SomeClass.someFunction(ref someDataMember); 
    } 

    static void someFunction(ref int i) 
    { 
     i = 42; 

     int[] dummy = new int[1234567890]; 
     // suppose the Garbage Collector kicks in here 

     i = 97; 
    } 
} 

CLR đảm bảo thông số tham chiếu không trở nên không hợp lệ trong khi thu thập rác? Chúng có được điều chỉnh giống như tham khảo lớp học không?

+1

có thể trùng lặp của [tham số C# bằng tham chiếu và thu gom rác .net] (http://stackoverflow.com/questions/2500851/c-sharp-parameters-by-reference-and-net-garbage-collection) –

+0

Eric Câu trả lời của Lippert cho câu hỏi được liên kết của @ rightfold trả lời điều này một cách hoàn hảo. –

+0

Chúng được điều chỉnh, bởi vì bất kỳ tham số phương pháp nào được coi là gốc, và tất cả các gốc đều được điều chỉnh (nó nói trong cuốn sách "CLR via C#") –

Trả lời

5

Vâng, cuộc sống không dễ dàng cho người thu gom rác. Nhưng nó biết làm thế nào để đối phó với con trỏ nội thất như thế này. Cũng ẩn từ các ngôn ngữ được quản lý như C# và VB.NET, nó có thể nhìn thấy trong C++, nơi con trỏ bên trong có thể dễ dàng được tạo ra bởi cú pháp ngôn ngữ. Stan Lippman của C++ Primer nổi tiếng có một số blog post về chúng, tạo ra động lực chính cho từ khóa interior_ptr có sẵn trong C++/CLI.

jitter vượt quá bước này, nó đánh dấu tham chiếu là GC_CALL_INTERIOR, cho biết trường hợp cụ thể của đối số có thể là con trỏ bên trong. Bạn có thể xem cách nó đang được xử lý bên trong GC với mã nguồn có sẵn từ bản phân phối SSCLI20. Nó không phải là khủng khiếp phức tạp, một đoạn từ gcsmp.cpp,() phương pháp GCHeap :: kỳ

if (flags & GC_CALL_INTERIOR) 
    { 
     if ((o < gc_heap::gc_low) || (o >= gc_heap::gc_high)) 
     { 
      return; 
     } 
     o = gc_heap::find_object (o, gc_heap::gc_low); 

     offset = (BYTE*)object - o; 
    } 

Vì vậy, trong Tóm lại, một thử nghiệm rất nhanh chóng phát hiện ra rằng nó không thể là một con trỏ mà tham chiếu một thành viên của một đối tượng kiểu tham chiếu bằng cách kiểm tra con trỏ dựa vào phân đoạn heap của GC thấp hơn/giới hạn trên. Sau đó, một chút đào để ánh xạ con trỏ bên trong đến đối tượng chứa thành viên đó. Hãy xem mã nguồn SSCLI20 để xem mã đó.

0

Bộ gom rác giữ một danh sách tất cả các con trỏ đến một đối tượng. Nó chỉ xử lý các đối tượng nếu không có thêm con trỏ tới đối tượng này.
Trong trường hợp của bạn, hàm của bạn sẽ có một con trỏ tới đối tượng (có tên là "i") và do đó GC sẽ không bao giờ vứt bỏ đối tượng này.

Bạn có thể đọc toàn bộ bài viết về cách GC hoạt động here.

+0

Tôi đang nói về việc di chuyển các đối tượng còn sống, không vứt bỏ vật chết. (Ngoài ra, 'i' không" trỏ "vào một đối tượng, nhưng với một thành viên dữ liệu.) – fredoverflow

+0

Ok vậy bạn đang nói về pha nén của chỉ GC? – Fabske

Các vấn đề liên quan