1

我在 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()
        {
        }
    }
}

当匿名函数(本地 f = ...)从外部范围创建涉及 .NET 对象的闭包时,就会出现问题。只要 Lua 解释器还活着,我创建的 50 个 DotNetObject 类实例就永远不会被垃圾回收,即使在 Lua 中强制进行 GC 时也是如此。

在 MyClass.StoreFunction 中手动处理 LuaFunction (function.Dispose()) 对象可以解决问题,但这是不可取的,因为在我的实际应用程序中,我不知道函数何时会执行——或者它是否会执行。强迫我处置 LuaFunction 会改变应用程序的整个架构,因此我基本上是通过处置包含 LuaFunction 的对象以及包含该对象的对象,一直沿链向上进行手动内存管理。

那么,这是 LuaInterface 中的一个错误,还是我错误地使用了该库?非常感谢任何建议,谢谢!

4

0 回答 0