Out of memory in tight consing loop
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Triaged
|
Wishlist
|
Unassigned |
Bug Description
Dear SBCL-Team, an example is probably better than many words:
-------
stm@t420:~$ sbcl
This is SBCL 1.0.58, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (defun cnt ()
(let* ((back (cons 2 nil))
(front (cons 1 back)))
(loop do
(progn (rplacd back (cons 3 nil))
CNT
* (cnt)
Heap exhausted during garbage collection: 0 bytes available, 8 requested.
Gen StaPg UbSta LaSta LUbSt Boxed Unboxed LB LUB !move Alloc Waste Trig WP GCs Mem-age
0: 0 0 0 0 0 0 0 0 0 0 0 5368709 0 0 0.0000
1: 72561 0 0 0 39329 0 0 0 0 161083248 8336 5368709 0 0 1.0001
2: 129917 129915 0 0 61247 212 11 0 10 251468736 312384 2000000 61248 0 0.0000
3: 0 0 0 0 0 0 0 0 0 0 0 2000000 0 0 0.0000
4: 0 0 0 0 0 0 0 0 0 0 0 2000000 0 0 0.0000
5: 0 0 0 0 0 0 0 0 0 0 0 2000000 0 0 0.0000
6: 0 0 0 0 5706 1285 0 0 0 28635136 0 2000000 5559 0 0.0000
Total bytes allocated = 536546168
Dynamic-
GC control variables:
*GC-INHIBIT* = true
*GC-PENDING* = in progress
*STOP-
fatal error encountered in SBCL pid 18463(tid 3084621504):
Heap exhausted, game over.
Welcome to LDB, a low-level debugger for the Lisp runtime environment.
ldb>
-------
I found that when adding (gc :full t) to the loop, the system seems to run ok:
(defun cnt2 ()
(let* ((back (cons 2 nil))
(front (cons 1 back))
(c 0))
(loop do
(progn
(incf c)
(when (zerop (mod c 100))
(gc :full t)
(setq c 0))
(rplacd back (cons 6 nil))
(setq back (cdr back))
(setq front (cdr front))
))))
Anyhow, this probably should not be necessay.
BTW, ECL has a similar problem while CLISP does fine.
My system:
Linux t420 3.2.0-39-
And *features*:
(:QUICKLISP :SB-BSD-
:COMMON-LISP :SBCL :SB-DOC :SB-TEST :SB-LDB :SB-PACKAGE-LOCKS :SB-UNICODE
:SB-EVAL :SB-SOURCE-
:OS-PROVIDES-
:OS-PROVIDES-PUTWC :OS-PROVIDES-DLADDR :OS-PROVIDES-DLOPEN :LITTLE-ENDIAN
:LINKAGE-TABLE :MULTIPLY-HIGH-VOPS :MEMORY-
:CYCLE-COUNTER :ALIEN-CALLBACKS :STACK-
:STACK-
:STACK-
:UNWIND-
:STACK-
:LINUX :ELF :UNIX :X86)
Kind regards,
Stefan Mandl
Changed in sbcl: | |
status: | New → Triaged |
importance: | Undecided → Wishlist |
This is the nature of conservative gcs; it is only related to Lisp insofar as SBCL and ECL have conservative gcs. When there is a boundlessly growing list as in your example, a cons may eventually be retained by the gc, whereupon infinite storage will be required. This is the "false positive" mentioned in
http:// en.wikipedia. org/wiki/ Garbage_ collection_ %28computer_ science% 29#Precise_ vs._conservativ e_and_internal_ pointers
The solution is to break the chain by replacing
(setq front (cdr front))
with
(setf front (prog1 (cdr front)
(setf (cdr front) nil)))
For performance reasons this should be probably done even in CL implementations that don't have a conservative gc, as it can significantly reduce a gc's workload.