Tôi đang viết một trình thông dịch lisp đơn giản từ đầu. Tôi có một môi trường toàn cầu mà các biến cấp cao nhất bị ràng buộc trong khi đánh giá tất cả các biểu mẫu trong một tệp. Khi tất cả các biểu mẫu trong tệp đã được đánh giá, mức env cao nhất và tất cả các cấu trúc dữ liệu giá trị khóa bên trong của nó được giải phóng.khi để giải phóng bộ nhớ của một đóng cửa trong một thông dịch viên lisp
Khi bộ đánh giá gặp mẫu lambda
, nó tạo đối tượng PROC
chứa 3 điều: danh sách đối số được gắn trong khung cục bộ khi áp dụng quy trình, phần thân của hàm và con trỏ đến môi trường nó đã được tạo ra trong Ví dụ:.
(lambda (x) x)
sẽ tạo ra một cái gì đó trong nội bộ như:
PROC- args: x,
body: x,
env: pointer to top level env
Khi PROC
được áp dụng, một môi trường mới được tạo cho khung và thứ e bindings địa phương được tổ chức ở đó để cho phép cơ thể được đánh giá với các ràng buộc thích hợp. Môi trường khung này chứa một con trỏ để đóng của nó để cho phép tra cứu biến bên trong R THNG. Trong trường hợp này, đó sẽ là môi trường toàn cầu. Sau khi cơ thể PROC
được đánh giá, tôi có thể giải phóng tất cả các ô được liên kết với nó bao gồm môi trường khung của nó và thoát ra mà không bị rò rỉ bộ nhớ.
Vấn đề của tôi là có chức năng đặt hàng cao hơn. Hãy xem xét điều này:
(define conser
(lambda (x)
(lambda (y) (cons x y))))
Một hàm lấy một đối số và tạo ra một hàm khác sẽ phản đối đối số của bạn đối với thứ bạn truyền vào nó. Vì vậy,
(define aconser (conser '(1)))
Sẽ mang lại một chức năng theo ý muốn '(1)
cho bất kỳ nội dung nào được chuyển vào đó. ví dụ:
(aconser '(2)) ; ((1) 2)
Vấn đề của tôi ở đây là aconser
phải giữ lại một con trỏ đến môi trường nó được thành lập năm, cụ thể là của conser
khi là được sản xuất thông qua gọi (conser '(1))
. Khi áp dụng aconser
, PROC
được áp dụng, khung của nó phải trỏ đến khung conser
đã tồn tại khi aconser
được xác định, vì vậy tôi không thể giải phóng khung conser
sau khi áp dụng. Tôi không biết làm thế nào/cách tốt nhất để giải phóng bộ nhớ liên quan đến khung lambda khi nó được áp dụng và cũng hỗ trợ loại hàm bậc cao liên tục này.
tôi có thể nghĩ ra một số giải pháp:
một số loại ARC
sao chép các môi trường kèm theo vào khung của PROC đánh giá khi nó được sản xuất
này dường như là những gì đang được ngụ ý here. Vì vậy, thay vì lưu một con trỏ trong đối tượng PROC để đóng cửa, tôi sẽ ... sao chép môi trường đóng và lưu con trỏ đến rằng trực tiếp trong ô?? Điều này sẽ không chỉ là đá một người có thể cấp sâu hơn và kết quả trong cùng một vấn đề?
- đệ quy thay thế các nhãn lúc đọc bên trong cơ thể của hàm bậc cao
tôi lo lắng tôi có thể thiếu một cái gì đó rất đơn giản ở đây, và tôi cũng tò mò như thế nào thủ tục này được hỗ trợ trong các triển khai khác của lisp và các ngôn ngữ khác có đóng cửa nói chung. Tôi đã không có nhiều may mắn tìm kiếm câu trả lời vì câu hỏi rất cụ thể, có lẽ ngay cả khi thực hiện điều này (rằng tôi thừa nhận rằng chỉ cần kéo mũ của mình như một dự án học tập) và phần lớn những gì tôi có thể tìm thấy của các đóng cửa từ ngôn ngữ đang được thực hiện, không phải từ ngôn ngữ mà ngôn ngữ đang được thực hiện trong.
Here is a link vào dòng có liên quan trong nguồn của tôi, nếu nó hữu ích và tôi rất sẵn lòng giải thích nếu câu hỏi này không đủ chi tiết để mô tả sự cố một cách kỹ lưỡng. Cảm ơn!
Tôi có thể thiếu thứ gì đó, nhưng bạn nói "sau khi cơ quan PROC được đánh giá, tôi có thể giải phóng tất cả các ô liên kết với nó bao gồm môi trường khung và thoát ra mà không bị rò rỉ bộ nhớ." Bạn không thể tái sử dụng việc đóng cửa nhiều lần? trong trường hợp này bạn sẽ giải phóng môi trường quá sớm. – coredump
Đó chính là vấn đề.Tôi đang vẽ một sự khác biệt ở đây giữa đóng cửa (bất cứ điều gì env một lambda xảy ra được đánh giá trong, kết quả là một proc) và khung, đó là các ràng buộc địa phương của các biến nội bộ để một proc khi nó được áp dụng. Tôi có thể hiểu lầm những thuật ngữ này trong lịch sử mặc dù ... – jfo
vì vậy nếu tôi có một lambda chỉ là một cấp độ sâu, khung của nó được tái tạo mỗi khi nó được áp dụng, sử dụng bất cứ điều gì args đã được chuyển cho nó. – jfo