ID:2842295
 
BYOND Version:514
Operating System:Windows 10 Home
Web Browser:Firefox 107.0
Applies to:Dream Daemon
Status: Open

Issue hasn't been assigned a status value.
Descriptive Problem Summary:
Some temporary lists that are a result of list operations with some built in procs (view, range, viewers, etc.) are kept alive even after the proc ends, and as such keep the objects they contain alive until the list is cleared when another similar loop construct is called.
Numbered Steps to Reproduce Problem:
1. Do a for(var/O in view(n) - someValue) while making sure there are atoms that view can return
2. Clear all the references you can that keep the atoms from the view call alive
3. The atoms don't get garbage collected as there's still a list keeping them alive

Code Snippet (if applicable) to Reproduce Problem:
atom/movable
Del()
world.log << "deleting [src] ([ref(src)])"
..()

mob
verb
DoBugView() // calling it once keeps the newly created objects alive even after the proc ends, calling it a second time clears the previous temporary list and releases the references to those objects which calls their Del() procs
for(var/turf/T in view(2))
var/obj/O = new(T)
O.name = "bugView"
for(var/obj/O in view(2) - src)
O.loc = null

DoBugRange() // same as the view version
for(var/turf/T in range(2))
var/obj/O = new(T)
O.name = "bugRange"
for(var/obj/O in range(2) - src)
O.loc = null

DoBugViewers() // same as the view version
for(var/turf/T in view(2))
var/mob/M = new(T)
M.name = "bugViewers"
for(var/mob/M in viewers(2) - src)
M.loc = null

ClearLastList() // calling this after calling any of the previous verbs releases the hidden temporary list and its contents
for(var/V in view() - 1)
V

CheckObjs() // used to see how many objs are kept alive
world << "Outputing objs"
for(var/obj/O)
world << O
world << "Done"

CheckMobs() // used to see how many mobs are kept alive
world << "Outputing mobs"
for(var/mob/M)
world << M
world << "Done"


Expected Results:
All temporary lists are released by the time the proc ends, so any items they contain can be properly garbage collected when needed.

Actual Results:
Sometimes a temporary list is kept alive even after a proc ends and through multiple other proc calls.

Does the problem occur:
Every time? Or how often? Every time
In other games? Yes
In other user accounts? Yes
On other computers? Yes

When does the problem NOT occur?
When list operations are not used as a direct statement in a loop setup.

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.)
Tested in 513.1542, 514.1589 and 515.1597, same result.

Workarounds:
Instead of doing for(var/O in view(n) - someValue) store the resulting list in a variable:
var/myList = view(n) - someValue
for(var/O in myList) ...
An update to the bug, the workaround actually isn't correct, and the bug has nothing to do with loops, it happens with all lists involving a call to one of the view/range/viewers/etc. procs, a temporary list stays alive until the next view/range/viewers/etc. call.

mob
verb
DoBugView2()
var/obj/O
for(var/turf/T in view(2))
O = new(T)
O.name = "bugView2"
var/list/l = view(2) // the view() list stays alive even after the proc ends

ClearLastList2()
var/list/l = view() // the previous temporary list is replaced with the new one, clearing all references

ClearObjLocs() // the objs should only have a loc as their only reference but clearing it doesn't cause them to get GCed
for(var/obj/O)
O.loc = null


This is likely some kind of caching behavior to save time on places where you call view() with the same parameters twice. That doesn't mean it's actually working correctly but I'm pretty sure I've heard caching being used in places like this in the past.