I’m currently learning about Object Oriented Programming and I’ve stumbled upon a problem. Whenever I’m destroying an object all variables that reference the object are not set to nil. I tried setting self to nil but the variables still reference my object. Here’s my code:
Module Script:
local ServerScriptService = game:GetService("ServerScriptService")
local Modules = ServerScriptService.Modules
local Janitor = require(Modules.Janitor)
local Signal = require(Modules.Signal)
local Object = {}
Object.__index = Object
function Object.new()
local self = {}
setmetatable(self, Object)
self._Janitor = Janitor.new()
self.Signal = self._Janitor:Add(Signal.new(),"DisconnectAll")
return self
end
function Object:Destroy()
self._Janitor:Destroy()
table.clear(self)
setmetatable(self, nil)
self = nil
end
return Object
Server Script:
local ServerScriptService = game:GetService("ServerScriptService")
local Modules = ServerScriptService.Modules
local Object = require(Modules.Object)
local newObject = Object.new()
print(newObject) --> table
newObject:Destroy()
print(newObject) --> empty table
Is there a way (apart from doing newObject = nil when an object is destroyed) to set all variables to nil that reference the object? If I’m understanding correctly the object doesn’t get garbage collected if I don’t do that.
According to Wikipedia “A memory leak may also happen when an object is stored in memory but cannot be accessed by the running code (i.e. unreachable memory)” which is the case here if I don’t manually set newObject to nil. Am I getting something wrong here?
My Tl;DR after reading is to destroy instances and connections. Other data types do not typically matter as after the variables are no long used it will be cleaned up. This means you only need to worry about it if there is an infinite loop and data keeps being created and stored in a table or creating instances and storing them in workspace.
Example testing, seems like :Destroy is not needed perhaps its an internal Roblox optimization? Safer to make sure the instances are destroyed with a function.
Thank you for your response and for linking the posts. It helped me understand garbage collection way better. One more question: How would I test my code for memory leaks?
If it’s leaking the graph will keep on increasing.
You can try this example of a memory leak:
--A real memory leak example
debug.setmemorycategory("Table with too many parts")
local untrackedtable = {}
game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
table.insert(untrackedtable,Instance.new("Part"))
end)