What causes a memory leak?

I’m making some code samples for use, and since I’m trying to improve my coding, I’m trying to make stopping memory leaks a habit.

But I haven’t done much research into the Luau garbage collector, so I’m not sure what can cause a memory leak.

I’ve done all the simple stuff, like setting all variables to nil after a connection function ends, removing unnecessary information from a table… but my code just isn’t big enough for me to test for memory leaks yet.

For an example, take a look at this code block:

collection:GetInstanceAddedSignal("Healer"):Connect(function(part)
	if part:IsA('BasePart') and part.HealingRange and part.HealingStrength then
		if not table.find(healparts, part) then
			table.insert(healparts, part)
		end
	else
		collection:RemoveTag(part, 'Healer')
	end
end)

or this line in particular:

collection:GetInstanceAddedSignal("Healer"):Connect(function(part)

Would part not being removed at the end of the connection cause issues?

basic stuff to prevent memory leaks:

  • disconnect functions when they are no longer being used even if it’s not working
  • clear/set variables to nil and delete parts

even if you don’t do these things, it probably won’t make much of a difference in performance unless you have a loop, then that would be bad

The only possible memory leak I can see in this code is that you aren’t removing parts from the healparts table, so that table could potentially become infinitely big, which would be a memory leak. part not being removed at the end won’t cause issues. Most of the memory leaks actually come from tables and elements not being cleaned up, so the tables just grow infinitely over time.

its being removed via this connection:

collection:GetInstanceRemovedSignal("Healer"):Connect(function(part)
	if table.find(healparts, part) then
		table.remove(table.find(healparts, part))
	end
end)

In that case I don’t see any leaks in this code.

well i do have this big while true loop that makes the heal parts work

while true do
	for _, char: Model in characters do
		for _, part in healparts do
			if (part.Position * Vector3.new(1, 0, 1) - char.HumanoidRootPart.Position * Vector3.new(1, 0, 1)).Magnitude <= part.HealingRange.Value then
				char.Humanoid.Health += part.HealingStrength.Value
				print('Part ' .. part.Name .. ' has healed you ' .. part.HealingStrength.Value .. '.')
			end
		end
		part = nil
	end
	char = nil
	wait(0.2)
end

you’re setting char and part to nil after they go out of scope, which now refer to globals; even then there’s no need to set stuff in a for loop to nil as it gets garbage collected anyway and doesn’t affect the table (like setting the parameters of a function)

You don’t need to set part or char to nil, and I don’t see any leaks here. There are some performance things you can do, though: cache the character’s Humanoid to save on performance from accessing children, but even that is microoptimisation. Any performance issues you have are probably going to be solved differently than stuff like this.

so basically

mismanaged connections = bad

mismanaged tables = bad

mismanaged everything else = meh

(outdated, reply was updated)
they’re not inherently bad, it’s just if you use them incorrectly it gets bad (adding things to a table and never removing them, connecting a bunch of stuff without disconnecting them once no longer needed, unless you destroy the instance)

This is wrong usage. Try:

table.remove(healparts, table.find(healparts, part))

yeah i already fixed that from bugfixing

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.