collectgarbage() won't fix memory leaks. collectgarbage("count") only retrieves the amount of used memory, it shouldn't affect program execution. It's weird that something stops working when you add collectgarbage("count"), unless it's something very timing-sensitive.
collectgarbage("count") will only retrieve the amount of memory used by Lua, but not by Löve objects. The size of Löve objects is not visible to Lua, and that's where the problem resides. If Lua does not find enough objects to clean, it won't collect garbage. But if the few existing objects are big, that may fill up the memory quickly.
For example, these two programs report the same memory usage:
Code: Select all
function love.load()
local x = love.image.newImageData(1,1) -- tiny image
print(collectgarbage("count"))
love.event.quit()
end
Code: Select all
function love.load()
local x = love.image.newImageData(4000,4000) -- huge image
print(collectgarbage("count"))
love.event.quit()
end
This program has no leaks, but it will quickly fill up the system memory for the reason mentioned above:
Code: Select all
function love.load()
for i = 1, 10000 do
local x = love.image.newImageData(1000,1000)
end
love.event.quit()
end
Each iteration, the old object that x was set to in the previous iteration, becomes unreferenced. It's the garbage collector's task to find these unreferenced objects and clean them up; however, from the point of view of the interpreter, 10,000 objects take just around a hundred KB, and it doesn't bother running the GC for that little. It doesn't know that each of these objects actually occupies around 4 MB.
That's just an unfixable bug in the garbage collector, not a memory leak. It's not a memory leak because if you had enough RAM, eventually the GC would run and clear all objects at once, and continue normally as if nothing happened. That's not happening because you don't have enough memory for the GC to do its job in the way it's designed to do it.
This program fixes the issue and does not fill up the system memory:
Code: Select all
function love.load()
for i = 1, 10000 do
collectgarbage()
local x = love.image.newImageData(1000,1000)
end
love.event.quit()
end
On each iteration, the garbage collector is forced to run, despite having just one new object every iteration. This keeps the memory usage under control.
A memory leak is a case where your program uses more and more objects without marking any of them for deletion. For example:
Code: Select all
local myObjects = {}
function love.update(dt)
table.insert(myObjects, love.image.newImageData(1, 1))
end
If nothing in your code clears any element of myObjects, you have a memory leak. Memory will grow and grow, and no call to collectgarbage() will fix it.