C#アプリケーションで最新バージョンのLuaInterface(http://code.google.com/p/luainterface/ )を使用しています。LuaクラスがObjectTranslatorの「objects」および「objectsBackMap」ディクショナリの内部参照をクリーンアップできず、メモリ使用量が常に増加するという問題が発生しています。
次のコードは問題を示しています。
public class Program
{
public static void Main()
{
Lua lua = new Lua();
string f = @"
return function(myClass, dotNetObject)
local f = function() dotNetObject:TestMethod() end
myClass:StoreFunction(f);
end";
var result = lua.DoString(f)[0] as LuaFunction;
MyClass testItem = new MyClass();
for (int i = 0; i < 50; i++)
{
DotNetObject o = new DotNetObject();
result.Call(testItem, o);
}
lua.DoString("collectgarbage()");
ObjectTranslator translator = (ObjectTranslator)typeof(Lua).GetField("translator", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(lua);
Console.WriteLine("Object count: " + translator.objects.Count);
//Prints out 51. 50 of these items are instances of 'DotNetObject', despite them being unreachable.
//Forcing a .NET garbage collection does not help. They are still being held onto by the object translator.
}
public class MyClass
{
public void StoreFunction(LuaFunction function)
{
//I would normally save off the function here to be executed later
}
}
public class DotNetObject
{
public void TestMethod()
{
}
}
}
この問題は、無名関数(local f = ...)が外部スコープからの.NETオブジェクトを含むクロージャを作成するときに発生します。Luaインタープリターが存続している限り、私が作成したDotNetObjectクラスの50個のインスタンスは、LuaでGCを強制した場合でも、ガベージコレクションされることはありません。
MyClass.StoreFunctionでLuaFunction(function.Dispose())オブジェクトを手動で破棄すると問題が解決しますが、実際のアプリケーションでは、関数がいつ実行されるか、または実行されるかどうかがわからないため、これは望ましくありません。LuaFunctionを破棄するように強制すると、アプリケーションのアーキテクチャ全体が変更され、基本的に、LuaFunctionを含むオブジェクトとそれを含むオブジェクトをチェーン全体で破棄することにより、手動でメモリ管理を行うようになります。
それで、これはLuaInterfaceのバグですか、それともライブラリを誤って使用していますか?どんなアドバイスも大歓迎です、ありがとう!