2009-08-03 21 views
6

Tôi hiểu rằng trong một ngôn ngữ được quản lý như Java hoặc C#, điều này được gọi là bộ thu gom rác mà mỗi lần kiểm tra xem có bất kỳ trường hợp đối tượng nào không còn được tham chiếu nữa, và do đó là hoàn toàn mồ côi, sau đó xóa hết bộ nhớ. Nhưng nếu hai đối tượng không được tham chiếu bởi bất kỳ biến nào trong chương trình, nhưng tham chiếu lẫn nhau (như đăng ký sự kiện), trình thu gom rác sẽ thấy tham chiếu này và không xóa các đối tượng khỏi bộ nhớ.Tại sao người thu gom rác không tìm ra được khi đối tượng tham chiếu eachother thực sự mồ côi

Tại sao điều này? Tại sao bộ thu gom rác không thể tìm ra rằng không phải đối tượng nào có thể được tham chiếu bởi bất kỳ phần hoạt động nào của chương trình đang chạy và xử lý chúng.

+5

Thực tế, đây là một trong những vấn đề với môi trường tính tham chiếu ** được xử lý ** trong .NET GC. –

+0

Tuy nhiên, một tính năng truyền thống của Lisp khác đang đi vào môi trường chính thống. –

Trả lời

24

Giả định của bạn không chính xác. Nếu GC 'thấy' (xem bên dưới) một tham chiếu tuần hoàn của 2 hoặc nhiều đối tượng (trong giai đoạn 'Mark') nhưng không được tham chiếu bởi bất kỳ đối tượng nào khác hoặc tay cầm GC cố định (tham chiếu mạnh), các đối tượng đó sẽ được thu thập (trong khi giai đoạn 'Sweep'.

Tìm hiểu sâu về bộ thu gom rác CLR có thể được tìm thấy trong this MSDN article và trong this blog post.

Lưu ý: Trong thực tế, GC thậm chí không 'nhìn thấy' các loại của các đối tượng trong dấu giai đoạn kể từ khi họ không thể truy cập, và do đó được thu thập trong một quét.

+0

Vâng ok làm cho mọi thứ dễ dàng hơn nhiều. Vì vậy, chương trình của tôi có cấu trúc cây tạo thành các nút, mỗi nút được hiển thị thông qua TreeNode tùy chỉnh trong một lần xem trang. Nếu không có gì liên quan đến Node hoặc TreeNode thì tôi không phải lo lắng về việc tách các sự kiện hoặc các tham chiếu giữa chúng. –

7

Hầu hết các GC không hoạt động với tính toán tham chiếu nữa. Họ thường (và đây là trường hợp cả trong Java và .NET) làm việc với khả năng tiếp cận từ tập hợp các đối tượng gốc. Tập hợp các đối tượng gốc là các hình cầu và các thể hiện được tham chiếu stack. Mọi thứ có thể truy cập từ tập hợp đó trực tiếp hoặc gián tiếp vẫn còn sống. Phần còn lại của bộ nhớ là không thể truy cập và do đó dễ bị thu thập.

+0

Trên thực tế, tôi nghĩ rằng đó là sai để gọi tham khảo-Đếm một hình thức của Garbage-Bộ sưu tập. Họ là 2 hình thức quản lý bộ nhớ riêng biệt. –

+0

Tính tham chiếu (RC) là dạng thu gom rác thải (GC). Thuật toán RC đơn giản không thể xử lý các tham chiếu tuần hoàn, nhưng có kỹ thuật của Bobrow, thuật toán con trỏ yếu và các thuật toán quét một phần có thể. – mtasic85

2

Tôi muốn thêm các sự cố xung quanh đăng ký sự kiện thường xoay quanh thực tế là người đăng ký & nhà xuất bản có vòng đời rất khác nhau.

Tự đính kèm ví dụ: với sự kiện Sự kiện App.Idle trong Windows Forms và đối tượng của bạn sẽ được giữ nguyên trong suốt thời gian còn lại của ứng dụng. Tại sao? Ứng dụng tĩnh đó sẽ giữ một tham chiếu (mặc dù gián tiếp thông qua một đại biểu) cho người quan sát đã đăng ký của bạn. Mặc dù bạn có thể đã xử lý người quan sát của bạn, nó vẫn còn gắn liền với App.Idle. Bạn có thể xây dựng nhiều ví dụ trong số đó.

1

Các câu trả lời khác ở đây chắc chắn là chính xác; .NET thực hiện thu gom rác dựa trên khả năng truy cập của một đối tượng.

Điều tôi muốn thêm: Tôi có thể khuyên bạn nên đọc Understanding Garbage Collection in .NET (bài viết đơn giản của Andrew Hunter) nếu bạn muốn có thêm thông tin chi tiết hơn.

2

Đây là nhược điểm lớn của truyền thống reference counting garbage collection. Thuộc tính của một bộ thu gom rác mô tả hành vi này là một bộ thu không đầy đủ. Những người thu gom khác phần lớn rơi vào một nhóm được gọi là truy tìm những người thu gom rác, bao gồm quét đánh dấu truyền thống, bán không gian/đầm nén và lai tạo thế hệ, và không bị những hạn chế này (nhưng phải đối mặt với nhiều người khác).

Tất cả các triển khai JVM và CLI Tôi biết sử dụng bộ thu hoàn chỉnh, có nghĩa là chúng không gặp phải vấn đề cụ thể mà bạn đang hỏi tại đây. Theo hiểu biết của tôi, trong số Jikes RVM là người duy nhất cung cấp bộ đếm đếm tham chiếu (một trong nhiều bộ sưu tập của nó).

Một điều thú vị cần lưu ý là có các giải pháp cho vấn đề đầy đủ trong bộ sưu tập đếm đếm tham chiếu, và resulting collectors chứng minh một số đặc tính hiệu suất thú vị khó thoát khỏi bộ thu thập truy tìm. Thật không may, các thuật toán thu gom rác đếm tham chiếu hiệu suất cao nhất và các sửa đổi hoàn chỉnh nhất dựa trên sự trợ giúp của trình biên dịch, do đó việc đưa chúng vào các số shared_ptr<T> của C++ rất khó khăn/không xảy ra. Thay vào đó, chúng tôi có weak_ptr<T>documented rules (xin lỗi về liên kết phụ tối ưu - dường như tài liệu hướng dẫn tôi) chỉ đơn giản là tránh các vấn đề. Điều này isn't the first time (một liên kết tầm thường) chúng tôi đã thấy cách tiếp cận này, và hy vọng là công việc bổ sung để ngăn chặn các vấn đề bộ nhớ ít hơn số lượng công việc cần thiết để duy trì mã không sử dụng shared_ptr<T>, v.v.

các liên kết tầm thường là vì nhiều tài liệu tham khảo của tôi nằm rải rác trong các ghi chú từ lớp quản lý bộ nhớ của học kỳ cuối cùng.

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