Closed mayoff closed 3 months ago
You are absolutely right about these observations, I ran into these while cooking the tests, and noticed the 2D tests fail and spent some quality time trying to figure it out, when I saw that I decided to check on the bug again and saw your analysis.
Love your patch, and the additional insight on the differences on those built-in types.
This patch addresses both leaks discussed in #513.
First leak
The changes in https://github.com/migueldeicaza/SwiftGodot/commit/d1d6ca47f0fc5bb16948017e1a6b2c6c8838b3b5 made several
Geometry2DTests
fail.The actual unbalanced retain causing the leak in
VariantRepresentable.swift
:The
variant.toType
function calls into Godot to copy out the built-in type stored invariant
. If that built-in type has an internal reference count, Godot increments it. Then, the call toself.init(content: content)
increments the count again. The retain performed byvariant.toType
is never balanced.This patch fixes the bug by generating a new
init(alreadyOwnedContent:)
initializer for each Godot builtin class type. This needs to be on the builtin wrappers (likeGDictionary
,GArray
, etc.), rather than onVariant
which is where https://github.com/migueldeicaza/SwiftGodot/commit/d1d6ca47f0fc5bb16948017e1a6b2c6c8838b3b5 put it.This patch also adds a test case to check for the leak by looking at Godot's
MEMORY_STATIC
performance counter, which is only enabled if Godot was built withDEBUG_ENABLED
.Second leak
This patch adds a test for the second leak described in https://github.com/migueldeicaza/SwiftGodot/issues/513, and fixes the leak.
Without this patch, the leak happens because
Variant.asObject
has an unneeded call torc.reference()
which increments theRefCounted
object's reference count. As far as I can tell, nothing balances this increment.Variant.asObject
callslookupObject(nativeHandle:)
, which returns a Swift wrapper for an object whose reference count has already been incremented (if the object isRefCounted
). The Swift wrapper balances that increment with a decrement in itsdeinit
.