gc full doesn't clean weak-pointer in class instance slot
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Invalid
|
Undecided
|
Unassigned |
Bug Description
I'm not sure that whether it's a bug, but here is the description.
1. Why does behavior of this too form is different?
The first form uses bar structure for holding an array of foo structure with a weak pointer:
(progn
(defstruct foo
(ref nil :type (or null sb-ext:
(defstruct bar
(items (make-array (list 1) :element-type 'foo :initial-element (make-foo))
:type (simple-array foo)))
(let ((bar-obj (make-bar)))
(let* ((val (list 10)))
(setf (aref (slot-value bar-obj 'items) 0)
(sb-ext:gc :full t)
(print (aref (slot-value bar-obj 'items) 0))))
This form produces expected print with the broken weak pointer:
#S(FOO :REF #<broken weak pointer>)
The second form uses bar class for holding an array of foo structure with a weak pointer:
(progn
(defstruct foo
(ref nil :type (or null sb-ext:
(defclass bar-class ()
((items :type (simple-array foo)
(let ((bar-obj (make-instance 'bar-class)))
(let* ((val (list 10)))
(setf (aref (slot-value bar-obj 'items) 0)
(sb-ext:gc :full t)
(print (aref (slot-value bar-obj 'items) 0))))
This form produces the print with the same weak pointer:
#S(FOO :REF #<weak pointer: (10)>)
2. I'm using sbcl 1.3.14.
3. Linux dlyman 4.4.0-127-generic #153-Ubuntu SMP Sat May 19 10:58:46 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Not a bug.
To assert stuff about what is/isn't provably reachable in such a narrow scope as these contrived examples, you have to make sure that local variables aren't acting as roots.
A pointer to the recently consed list may linger on the stack for various reasons.
In case it does; in the other case it doesn't. There's nothing to explain this at the language level; it's based on the assembly code's behavior, and whether the stack frame word that held a pointer to the thing you expect to have become unreachable got overwritten.