2010-06-04 69 views
12

Không giống như Java, Perl sử dụng số tham chiếu để thu gom rác thải. Tôi đã thử tìm kiếm một số câu hỏi trước đó mà nói về C + + RAII và con trỏ thông minh và Java GC nhưng đã không hiểu làm thế nào Perl đề với các vấn đề tham chiếu tròn.Thu gom rác trong Perl

Có ai có thể giải thích cách bộ thu gom rác của Perl đề cập đến các tham chiếu vòng tròn không? Có cách nào để đòi lại bộ nhớ tham chiếu vòng tròn mà không còn được sử dụng bởi chương trình hay không Perl chỉ bỏ qua vấn đề này hoàn toàn?

Trả lời

13

Theo bản sao của tôi Lập trình Perl 3rd ed., khi thoát Perl 5 thực hiện "đánh dấu tốn kém và quét" để xác nhận lại các tham chiếu vòng tròn. Bạn sẽ muốn tránh tham chiếu vòng tròn càng nhiều càng tốt vì nếu không chúng sẽ không được khai hoang cho đến khi chương trình thoát.

Perl 5 cung cấp tham chiếu yếu qua mô-đun Scalar::Utils.

Perl 6 sẽ chuyển sang sơ đồ thu gom rác có thể cắm được (tốt, underlying VM will have multiple garbage collection options và hành vi của các tùy chọn đó có thể có tác dụng trên Perl). Đó là, bạn sẽ có thể lựa chọn giữa các nhà sưu tập rác khác nhau, hoặc thực hiện của riêng bạn. Bạn muốn một nhà sưu tập sao chép? Chắc chắn rồi. Muốn một bộ sưu tập màu? Bạn hiểu rồi. Đánh dấu/quét, nén, vv? Tại sao không?

+4

Nit: Perl 5 sử dụng tính tham chiếu. Đó là một chương trình thu gom rác thải. – tsee

+0

OK, tôi đã sửa đổi tham chiếu đến bộ sưu tập rác Perl 6. –

+1

Cảm ơn bạn đã cập nhật câu trả lời. NB: Những người thu gom rác cồng kềnh có vẻ như là một ý tưởng khủng khiếp. Một cách tuyệt vời để làm chậm mọi thứ và/hoặc tạo ra hành động đáng ngờ ở khoảng cách khi cắm các bộ thu gom rác, những lời hứa khác nhau về thời gian GC. – tsee

-8

Perl áp dụng GC thay thế đánh dấu và quét trong một số trường hợp (khi một chuỗi chết, tôi nghĩ) để xác nhận lại tham chiếu vòng tròn. Lưu ý rằng "mọi giá trị là một chuỗi" Perl stanza gây khó khăn cho việc tạo các tham chiếu vòng tròn đúng; điều này là khả thi, nhưng mã Perl "bình thường" thì không, đó là lý do tại sao việc đếm tham chiếu hoạt động tốt với Perl.

+0

Cách nhanh chóng để rò rỉ một cuộc gọi perl SV 'rò rỉ phụ {my $ r; $ r = \ $ r; } ' Trong khi đây là một ví dụ giả tạo, nó không khó để làm tương đương mà không nhận thấy nó. –

+7

Điều này là đơn giản sai; Perl không * không * tin rằng mọi giá trị là một chuỗi. 'my $ hashref = {a => 1};' lá '$ hashref' làm tham chiếu thực, không phải chuỗi. Điều này đã đúng kể từ khi Perl 5 ra mắt vào tháng 10 năm 1994 ** - 17 năm trước. (Tất nhiên, Perl sẽ vui vẻ chuyển đổi tham chiếu thành chuỗi, nhưng chuyển đổi đó là một chiều) – derobert

2

Câu trả lời nhanh là Perl 5 thực hiện không phải xử lý tham chiếu vòng một cách tự động. Trừ khi bạn thực hiện các biện pháp rõ ràng trong mã của mình, bất kỳ cấu trúc dữ liệu nào của bạn bao gồm tham chiếu vòng tròn sẽ không được khôi phục cho đến khi chuỗi tạo chúng chết. Đây được coi là một sự cân bằng có thể chấp nhận được ở chỗ nó tránh được sự cần thiết cho việc thu gom rác thời gian chạy sẽ làm chậm quá trình thực thi.

Nếu mã của bạn tạo cấu trúc dữ liệu với tham chiếu vòng tròn (nghĩa là cây có nút chứa tham chiếu về gốc), bạn sẽ muốn sử dụng mô-đun Scalar :: Util để "làm suy yếu" các tham chiếu trỏ ngược về gốc nút. Các tham chiếu yếu này sẽ không thêm vào số tham chiếu của bất kỳ thứ gì chúng trỏ tới, do đó toàn bộ cấu trúc dữ liệu sẽ tự động được phân bổ khi tham chiếu bên ngoài cuối cùng biến mất.

Ví dụ:

use Scalar::Util qw(weaken); 

... 

    my $new_node = { content => $content, root => $root_node }; 
    weaken $new_node->{root}; 
    push @{$root_node->{children}}, $new_node; 

Nếu bạn sử dụng mã như thế này bất cứ khi nào bạn thêm các nút mới để cấu trúc dữ liệu của bạn, sau đó các tài liệu tham khảo chỉ vào thư mục gốc được thực tính là những từ bên ngoài của cấu trúc. Đây chính là điều bạn muốn. Sau đó, các gốc, và đệ quy tất cả các con của nó, sẽ được khai hoang ngay khi tham chiếu bên ngoài cuối cùng để nó biến mất.