Lua - 延迟调用类的析构函数

4
我正在开发一个C++程序,它本质上只是执行Lua脚本。在该Lua脚本中,构造了从我的C++程序导出的类。
我的main() C++函数在做一些准备工作后调用...
    luabind::call_function<void>(m_L, "main");

现在我的 Lua 脚本看起来像这样:
local function test()
local c = C()
end

function main()
    for i=1,2 do
        log(i)
        test()
    end
end

我在 C 的析构函数中加入了 std::cout << "destructor" << std::endl;,这样我就可以知道何时调用它。我期望 lua 的垃圾回收每次在 test() 执行结束时调用 c 的析构函数,因为这时它已经超出了范围。然而,我看到以下输出:

1
2
destructor
destructor

相比之下
1
destructor
2
destructor

有人知道这是为什么吗?我有什么遗漏的吗?
1个回答

8
我原以为lua的垃圾回收会在每次执行test()结束时调用c的析构函数,因为这时c已经超出了作用域。但事实并非如此。与其他垃圾回收语言一样,你不能依赖于析构函数何时运行,而且在某些语言中,对象可能永远不会被销毁。无法像C++那样使Lua自动按确定性方式销毁对象。如果必须依赖这一点,则可以使用Lua的collectgarbage功能,但最好根据需要重新设计。关于Lua的垃圾收集如何工作,可以参考这里。下面是使用collectgarbage的示例:
local function test()
    local c = C()
end

function main()
    for i=1,2 do
        log(i)
        test()
        collectgarbage "collect"
    end
end

嗯,这真是令人不愉快。现在,我为了清晰起见已经简化了这个例子,但在我的实际应用中,c是一个非常庞大的对象(大约100-1000 MB)。需要进行清理!有没有办法从Lua中获得我期望的行为? - chris.schuette
1
@chris.schuette:如果你真的需要,你可以手动调用垃圾回收器 - 在C中使用lua_gc或在Lua中使用collectgarbage - sbk
如果你想要一个更细粒度的解决方案,你可以让 Lua 调用对象上的一个函数来删除它。显然,Lua 脚本在此之后必须确保不再操作该对象。 - Nicol Bolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接