Question’s in the title. If that’s unclear, my example scenario should better explain it.
So take this piece of code I wrote, which was pointed out to me privately that it leaks memory.
local accessories = humanoid:GetAccessories()
for _, accessory in ipairs(accessories) do
if accessoryMeetsDeletionCriteria(accessory) then
accessory:Destroy()
end
end
References to Roblox instances are strong by default, so this code sample leaks memory. The obvious solution would be to set the index to nil after destroying it so the instance loses all references and can be properly garbage collected.
local accessories = humanoid:GetAccessories()
for index, accessory in ipairs(accessories) do
if accessoryMeetsDeletionCriteria(accessory) then
accessory:Destroy()
accessories[index] = nil
end
end
What happens if I lose a reference to the table? Does the table still exist in memory and not get garbage collected, along with the references its holding to Roblox instances? I don’t know if I’m correct or not, but I believe I can lose table references in two ways, so I’m curious to know if either of them leak memory and if I should opt for explicit reference loss like the above.
Both methods are as follows:
-- Forego variable, place table creation directly as the generator argument.
-- This actually doesn't lose the reference, rather, I don't have one at all.
-- The generator may hold a reference to the table though.
for _, accessory in ipairs(humanoid:GetAccessories()) do
if accessoryMeetsDeletionCriteria(accessory) then
-- Can't set index to nil because I have no reference to the table
accessory:Destroy()
end
end
-- The obvious other alternative is explicitly dropping the reference
local accessories = humanoid:GetAccessories()
for _, accessory in ipairs(accessories) do
if accessoryMeetsDeletionCriteria(accessory) then
accessory:Destroy()
end
end
accessories = nil
When you call a function like :GetChildren or :GetDescendants, and in your case :GetAccessories, Roblox returns a new table. The generator function ipairs and its counterparts don’t keep a reference to the table given so it won’t leak that way. When you are doing something like
x = { { }, function() end, newproxy(false) }
x = nil
The elements inside do get collected eventually since there is no more strong references to them. And of course the table x points to also gets collected.
So essentially: even if that table has strong references in it, there’s no reference to the table, so the table and the references its holding are eligible for garbage collection. Would that effectively mean that any code samples other than the first don’t leak memory?
I know. But do you know for certain that internally that __gc does not exist? There is no need for it w/ tables or newproxy, but when you actually have have allocations on the native code side, then it’s a different story.
__gc is not even just disabled, it is completely removed. i have a reputable source which i will send you in dms since i dont want to clutter the thread.
Glad to see you’re interested in the thread, however this discussion isn’t exactly relevant to the question I had asked. It would be much appreciated if further conversation were moved to DMs.