Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Đếm tham chiếu và rác chu trình bị rò rỉ

    Nhược điểm nổi tiếng của đếm tham chiếu (reference counting) là không thể tự thu hồi các chu trình tham chiếu (reference cycle) không còn được gốc (root) trỏ tới — vì các object trong chu trình vẫn giữ tham chiếu lẫn nhau nên refcount không bao giờ về 000, dẫn tới rò rỉ bộ nhớ (memory leak).

    Cho nnn object (id 1..n1..n1..n), mỗi object có bộ đếm tham chiếu rcrcrc (ban đầu 000). Có qqq thao tác lần lượt:

    • ROOT r: thêm một tham chiếu gốc tới rrr (rcr+=1rc_r \mathrel{+}= 1rcr​+=1).
    • UNROOT r: bỏ một tham chiếu gốc khỏi rrr (rcr−=1rc_r \mathrel{-}= 1rcr​−=1; đảm bảo có ít nhất một tham chiếu gốc đang tồn tại tới rrr).
    • REF a b: object aaa (còn sống) thêm một tham chiếu tới object bbb (còn sống) (rcb+=1rc_b \mathrel{+}= 1rcb​+=1).
    • UNREF a b: object aaa bỏ một tham chiếu tới bbb (rcb−=1rc_b \mathrel{-}= 1rcb​−=1; đảm bảo tham chiếu này đang tồn tại).

    Mỗi khi rcrcrc của một object về 000 (do UNROOT/UNREF), object đó lập tức bị giải phóng theo kiểu cascade: mọi tham chiếu mà chính nó đang giữ tới các object khác cũng bị hủy (refcount các object bị trỏ tới giảm tương ứng), có thể kéo theo giải phóng dây chuyền tiếp. (Đề bài đảm bảo mọi thao tác chỉ nhắc tới object còn sống tại thời điểm đó.)

    Sau khi xử lý xong tất cả thao tác, tìm các object rác chu trình bị rò rỉ: object còn "sống" (chưa từng bị giải phóng, rc>0rc>0rc>0) nhưng không thể với tới được từ bất kỳ tham chiếu gốc nào hiện tại (qua các cạnh tham chiếu còn tồn tại) — chính là bộ nhớ mà reference counting đã "bỏ sót", cần một GC dạng tracing (như mark-sweep) mới thu hồi được. (Object chưa từng được tham chiếu lần nào, rc=0rc=0rc=0 từ đầu tới cuối, không được tính là rò rỉ.)

    Yêu cầu: in danh sách id object rò rỉ (tăng dần), hoặc NONE; dòng tiếp theo in số lượng object rò rỉ.

    Ví dụ: n=2n=2n=2. ROOT 1; REF 1 2; REF 2 1; UNROOT 1. Sau UNROOT 1: rc1=1rc_1=1rc1​=1 (còn tham chiếu từ object 222), rc2=1rc_2=1rc2​=1 (còn tham chiếu từ object 111) — cả hai vẫn "sống" theo refcount nhưng không còn gốc nào trỏ tới, tạo thành chu trình rò rỉ: in 1 2 và số lượng 2.

    • Định dạng đầu vào:

      Dòng 1: nnn (1≤n≤1001 \le n \le 1001≤n≤100). Dòng 2: qqq (0≤q≤5000 \le q \le 5000≤q≤500). qqq dòng: ROOT r / UNROOT r / REF a b / UNREF a b.

    • Định dạng đầu ra:

      Dòng 1: danh sách id rò rỉ tăng dần cách nhau bởi dấu cách, hoặc NONE. Dòng 2: số lượng.

    Ví dụ:

    Đầu vào:

    2
    4
    ROOT 1
    REF 1 2
    REF 2 1
    UNROOT 1
    

    Đầu ra:

    1 2
    2
    

    Đầu vào:

    3
    4
    ROOT 1
    REF 1 2
    REF 2 3
    UNROOT 1
    

    Đầu ra:

    NONE
    0
    

    Đang tải editor...