2012-02-18 17 views
3

我對REPL中的SBCL垃圾收集器的以下行爲感到有些莫名其妙。定義兩個功能:SBCL的REPL中的內存泄漏

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

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

然後運行

(add-one (test-gc)) 

我希望沒什麼引用原始數組了。然而,作爲(空間)報告,內存不會被釋放。我會明白,如果我跑(測試-GC)直接,那麼一些參考可能已經在某處泥或

(list * ** ***) 

卡住了,是這裏的情況?謝謝,安德烈。

更新前段時間我提出了一個錯誤。最近證實。參見: https://bugs.launchpad.net/sbcl/+bug/936304

+0

您可能想在SBCL郵件列表 – 2012-02-18 21:42:34

+0

上提出這個問題......並且可能會在此發佈後續回覆。順便說一句,爲什麼在問題的標題中「關閉」?我沒有看到問題代碼中的任何關閉。 – 2012-02-19 13:25:51

+1

我試過CLISP中的相同代碼,沒有問題。 SBCL的git版本仍然存在這個問題,所以我提交了一個錯誤報告:(https://bugs.launchpad.net/sbcl/+bug/936304)。關於結束語,沒有結束:) – Andrei 2012-02-19 15:52:34

回答

4

僅僅因爲沒有引用對象,並不意味着內存將被回收。垃圾收集器將在未來運行一段時間,並且通常您獲得的唯一保證是它會在出現內存不足錯誤之前運行。

此處可能發生的另一件事是您正在查看Lisp進程的內存使用情況。當內存是CG時,通常不會返回到操作系統。相反,內存在堆上簡單標記爲空閒,並可用於將來的內存分配。只有

+2

有效的點,我沒有想到這一點。所以我做了一個進一步的測試:評估'(add-one(test-gc))'幾次。如果任一點是有效的,那麼我應該永遠不會用完內存。然而,經過幾次評估後,我得到了:「堆累」。因此,內存似乎沒有被釋放或重用。 – Andrei 2012-02-18 18:31:55

+0

我在Linux上的SBCL 1.0.53中看不到這個問題 – 2012-02-19 17:05:58

+0

有趣。我用1.0.54。我剛剛嘗試過1.0.53,但仍然出現錯誤(在Linux上也是這樣)。如果你在git版本中也沒有發生錯誤,你可以考慮共享(https://bugs.launchpad.net/sbcl/+bug/936304)。 – Andrei 2012-02-19 18:13:54

1

SBCL ...

(gc :full t)

這將強制在所有代揭開序幕垃圾收集。我注意到SBCL在幾天前保存了大量內存,並使用它將內存降低到「真實」使用。

然後,我寫了一個ensure-gc宏來包裝我的垃圾計算&實驗的東西。如果我記得,我會在回家的時候粘貼它...這不是什麼幻想。

+0

強制垃圾收集工作,但只有在我已經多次評估(add-one(test-gc))之後。滑稽。 – Andrei 2012-02-26 14:57:58

+0

@Andrei:我必須通過:充分確保它貫穿所有世代。 – 2012-02-26 16:50:04