This article uses one of the most common cases of memory leaks caused by lua and C#/C++ circular references to analyze the causes and solutions.
Article Directory
Circular reference case
The circular reference caused by the button binding anonymous function (closure):
self.Button.OnClicked:Add(function()
self:doSomething(true)
end)
reason
Circular reference chain:
UIBP(self)------->Button------>luaFunction------>UIBP(self)
Lua refers to the C++ object Button, and Button refers to the closure of Lua. An upvalue——self is used in the closure, and this self refers to a UIBP, and UIBP refers to Button
Simply put, the lua function refers to a C++ object, and the C++ object refers back to the same lua function. When the GC detects references, the UI cannot be recycled
solution
Just remove one of the references in the circular reference chain
untie
self.Button.OnClicked:RemoveAll()
After unbinding the delegate, there is no reference from Button to luaFunction, which also breaks the chain of circular references:
UIBP(self)------->Button—×—>luaFunction------>UIBP(self)
Ensure that there is no strong reference to itself in the bound luaFunction
pass self using weak reference
function UIBPName:f1()
self:doSomething(true)
end
self.Button.OnClicked:Add(self.f1, self)
Add
The first parameter of the method is a strong reference, and the second parameter is a weak reference. Equivalent to breaking the chain of circular references:
UIBP(self)------->Button------>luaFunction—×—>UIBP(self)
The reason for the strong reference to the first parameter is to ensure that the anonymous function can be passed in as the first parameter.
Do not use strong references to self in methods
local f1 = func()
UIBP:doSomething(true)
end
self.Button.OnClicked:Add(f1)
This method can ensure that even if you forget to unbind, there will be no memory leaks
Tips :
It is best not to write this kind of local f1 in the function to prevent value storage