ローカル変数の罠
--test.lua local a = 1 local b = 2 local c = 3 local d = { 1, 2, 3, 4, 5, } lua_test = { OnUpdate = function(this) print("call lua_test::OnUpdate( a=" .. a .. ",b=" .. b .. ",c=" .. c .. " )\n") end, OnFinalize = function(this) a = nil b = nil c = nil d = nil end, }
結果
call lua_test::OnUpdate( a=1,b=2,c=3 )
上記のようなコードを書いて何度もdo_bufferしたりdo_fileしたりすると、local変数が消えずに残ってるような感じになってしまっている。
GCの値を表示してると徐々に増えていくのが分かると思う。
これが巨大なlistを持つlocal変数が沢山あると分かりやすいぐらいにCPU負荷があがって、
どんどんGCの境界値が上がっていってしまって、
コンシューマなんかだと割とあっという間にメモリを食いつぶし、
最後にはメモリリークのような感じで死んでしまう。
ぶっちゃけメモリリークと言ってしまってもいいと思う。
で、一応上記のようにOnFinalizeで全部の変数をnilにしておけば(参照先が)ガベージコレクターを呼んだ時に回収対象になるので問題ないのですが、local変数が大量にあると列挙するのも大変ですよね。
グローバルなlua_testのOnUpdateをC側から呼び出しても、local変数が参照できてるのでlua_setlocalなんかを使ってnilにしていけばいいかなぁとか思ったらどうやらそうも行かない模様で、
local a = { 2, 3, 4, } local v = { 2, 3, 4, } local d = { 2, 3, 4, } local s = { 2, 3, 4, } lua_test = { OnFinalize = function(this) delvars(1) end, } lua_test:OnFinalize()
lua_testのスコープ外からこんな感じで呼び出せば全てのlocal変数は消えるんだけど、
Cから呼び出すと消えない。
というかその場合、関数内部で参照している変数を消しに言ってしまう。
よくよく調べるとCから呼び出した場合、
中で参照しているlocal変数は上位値で渡されているのが分かる。
要するに隠し変数みたいな感じで渡されているので、
Cから呼び出したOnFinalizeでlocal変数を操作しようと思ったら、
結局全部手動で列挙していかなければならないので意味が無いという事だ。
ということで自動でlocal変数が消せないのですごく困っています。
誰か助けて!