SBCL的REPL中存在内存泄漏问题

3

我很困惑SBCL垃圾收集器在REPL中的以下行为。定义两个函数:

(defun test-gc ()
  (let ((x (make-array 50000000)))
    (elt x 0)))

(defun add-one (x) (+ 1 x))

然后运行

(add-one (test-gc))

我期望原始数组不再被引用。然而,正如(room)所报告的那样,内存并没有被释放。如果我直接运行(test-gc),那么我可以理解,可能在SLIME或其他地方仍然有一些引用。

(list * ** ***)

这里的情况是什么?谢谢,Andrei。

更新 一段时间以前,我提交了一个错误报告。最近已经得到确认,请参见:https://bugs.launchpad.net/sbcl/+bug/936304


你可能想在SBCL邮件列表上提出这个问题。 - Rainer Joswig
...并且也许在这里发布他们回复的跟进。顺便问一下,为什么问题的标题中有“闭包”?我在问题的代码中没有看到任何闭包。 - Miron Brezuleanu
1
我在CLISP中尝试了相同的代码,没有问题。SBCL的git版本仍然存在这个问题,所以我提交了一个错误报告:(https://bugs.launchpad.net/sbcl/+bug/936304)。关于闭包的评论,实际上并没有闭包 :) - Andrei
正如我在那个错误报告中提到的,这个错误仍然存在,尽管已经标记为关闭。我还报告了类似的 https://bugs.launchpad.net/sbcl/+bug/1009267。开发人员似乎对这些问题非常(令人不安地)不感兴趣,尽管在我看来这是一个重大问题。 - Faheem Mitha
2个回答

5

虽然没有任何东西再引用这些对象了,但这并不意味着内存将被回收。垃圾回收器将在未来某个时间运行,通常您能获得的唯一保证是它将在您收到内存不足错误之前运行。

这里可能发生的另一件事是您正在查看Lisp进程的内存使用情况。当内存被CGed时,通常不会将其返回给操作系统。相反,内存只是在堆上标记为自由状态,并可用于以后的内存分配。


2
有些观点很有道理,我之前并没有考虑到。所以我又进行了一次测试:对(add-one (test-gc))进行多次评估。如果其中任何一个观点是正确的,那么我就不应该会出现内存耗尽的情况。然而,经过几次评估后我却得到了“堆耗尽”的警告。这表明内存并没有被释放或重复利用。 - Andrei
我在Linux上的SBCL 1.0.53中没有看到这个问题。 - Vsevolod Dyomkin
有趣。我使用的是1.0.54版本。我刚刚尝试了1.0.53版本,但我仍然遇到了错误(在Linux上也是如此)。如果您在git版本中没有遇到此错误,您可以考虑在(https://bugs.launchpad.net/sbcl/+bug/936304)上分享。 - Andrei

1

仅限于SBCL...

(gc :full t)

这将强制在所有代际之间启动垃圾回收。我几天前注意到SBCL占用了大量内存,使用此方法将内存降至“真实”使用情况。

然后,我编写了一个确保垃圾计算和实验内容的ensure-gc宏。如果我记得的话,我会在回家后粘贴它...它不是很花哨。


强制垃圾回收是有效的,但只有在我评估了(add-one(test-gc))不止一次之后才有效。很有趣。 - Andrei
@Andrei:我必须传递 :full 以确保它通过所有的生成。 - Paul Nathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接