2

在运行时包含编译器的多种(可能是大多数)语言实现忽略了垃圾收集丢弃的代码(例如,参见,这会导致等应用程序中的内存泄漏)

我的初步测试表明 Chez Scheme 不会在这里泄漏内存,但我想更确定地知道,因为我什至不知道是否f并且g 实际上被编译了。(古老的口头禅:“测试只能证明错误的存在,而不是它们的缺失”)


我尝试的测试:fg互相调用,它们的定义在运行时被替换。

(define f)
(define g)

(define (make-f x)
  (eval `(set! f (lambda (y)
           (if (> y 100)
             (+ (remainder ,x 3) (g y))
             (+ y 1))))))

(define (make-g x)
  (eval `(set! g (lambda (y)
           (if (< y 10)
             (+ (remainder ,x 5) (f y))
             (div y 2))))))

(define (make-and-run-f n)
  (begin
    (make-f 1)
    (make-g 1)
    (let loop ((i 0) (acc 0))
      (if (> i n)
        acc
        (begin
            (make-f i)
            (make-g i)
            (loop (+ i 1) (+ acc (f 33))))))))

(time (make-and-run-f 1000000)) ; runs in 10 min and negligible memory
4

1 回答 1

1

鉴于过程和垃圾收集对 Scheme 的重要性,如果 Chez Scheme 没有尝试对任何动态创建的对象进行垃圾收集,我会感到惊讶。R6RS 标准说[强调我的]:

在 Scheme 计算过程中创建的所有对象,包括过程和延续,都具有无限的范围。没有任何 Scheme 对象被销毁。Scheme 的实现不会(通常!)存储空间不足的原因是,如果它们能够证明该对象不可能对任何未来的计算产生影响,则允许它们回收对象占用的存储空间。

过程是一个对象,如果实现可以证明计算不再需要它,任何对象都可能被垃圾回收。这不是要求,但适用于任何对象,而不仅仅是过程。

不过,Chez Scheme 手册似乎是权威的(Chez Scheme 第 9 版用户指南,第 82 页)

由于所有的 Scheme 对象,包括代码对象,都可以被垃圾收集器重新定位甚至回收......

在 1990 年代,Kent Dybvig 与 David Eby 和 Carl Bruggeman 一起写了一篇论文,这里可能会感兴趣,名为Don't Stop the BIBOP: Flexible and Efficient Storage Management for Dynamically Typed Languages,描述了在 Chez Scheme 中实现的垃圾收集策略. 在本文中,花了一些时间讨论“代码对象”,特别是在垃圾收集过程中如何隔离和区别对待它们(因为它们可能包含指向其他对象的指针)。

于 2020-12-24T07:31:37.310 回答