Situational Garbage Collection Question

Hello everyone, I have a specific case question about whether or not a certain variable would be garbage collected.

Here is the case code:
local collectRequests = {}

function activateTouchConnection(newBlock)
	local touchConnection = newBlock.Touched:connect(function(Part)
		local playerWhoTouched = game.Players:FindFirstChild(Part.Parent.Name)

		if (playerWhoTouched ~= nil) then
			table.insert(collectRequests, 1, {
				player = playerWhoTouched;
				block = newBlock;
			})
		end
	end)
end

I was wondering: if the variable ‘playerWhoTouched’ inside the touchConnection is not nil, will it be garbage collected or will it remain in memory when touchConnection is disconnected and dereferenced? (either by destroying the block or calling :disconnect() and setting touchConnection = nil)

Are all local variables inside a connection garbage collected along with the connection?

playerWhoTouched is only going to be garbage collected once it’s out of the collectRequests table.

1 Like

Does the statement ‘player = playerWhoTouched’ link the variable or does it copy it? I thought it would copy playerWhoTouched, and thus playerWhoTouched wouldn’t be inside the table.

Oh, that’s what you meant. Yea, as long as playerWhoTouched isn’t a table (in this case it’s not), it’s going to get garbage collected once the function finishes. player = playerWhoTouched does copy the value.

What do you mean by ‘when the function finishes’

When there’s no code left in the function to call. In this case, after it’s done inserting it into the table.

1 Like

Lua works with references, apart from some primitives (numbers, booleans and string)
E.g.

local a = {}
local b = a -- just copies the reference
a.ABC = 123
print(b.ABC) --> 123 (a and b are the same thing) (same table in memory)

local player = getPlayer()
local anotherReference = player
-- anotherReference and player point to the same thing in memory

When a function ends, all local variables are removed from the stack, and if the values have no references, they will be (later on, when the next gc cycle hits) garbage collected. The only exception is with upvalues:

function test()
	local upval = {}
	return function() return upval end
end
local f = test()
-- f is a reference to that returned function
-- since test() ended, the locals get cleaned, but upval is still needed
-- Lua internally moves the upvalue to another place, nothing you should worry about
-- while the "variable" is gone, the table is still in memory (and accessible by f)
local t = f()
-- now we also have a reference to "upval" (not upval, but the table it got set to)
t,f = nil,nil -- set to nil (clear references)
-- f isn't referenced anymore, so it'll be garbage collected soon
-- t is only referenced by f, so once f is gc'd, t/upval can be gc'd too

The player object (and newBlock) objects are never GCed, since you add a reference to them in the table that’s in collectRequests.

If you’re new to programming, wrapping your head around references and GC is tricky. A good tip for Lua to remember is: If you can access it, it doesn’t get GCed (exception: if it’s a weak key/value for weak tables, but eh) e.g. you can access playerWhoTouched/newBlock via collectRequests, so they don’t get GCed.

Roblox makes it a bit more tricky with connections: as long as the connection is active (e.g. con.connected is true, so you didn’t call touchConnection:Disconnect() or newBlock:Destroy(), it’s (internally) referenced and can’t get GCed. The function you connected is also referenced, since it needs to be called when the event fires. All upvalues used by that function also don’t get GCed, as the function could use them.

If the above didn’t clear it up: That line “copies” the value, but since it isn’t a string/number/boolean, it actually copies the reference. Both point to the same player object, which won’t get GCed.

TL;DR and actual answer to your question:
The playerWhoTouched variable is removed when the function ends. You’re storing a reference to the actual Player object in the table, not a reference to the variable (that’s impossible in Lua), so the player object won’t get GCed

4 Likes