5

tl;dr 版本:如果垃圾收集元方法在 Lua 状态关闭期间访问全局变量,它是否安全?本地升值呢?


当 alua_State被关闭时lua_close,Lua 文档说所有对象都被删除。它说任何相关的垃圾收集元方法都保证被调用。

伟大的。

但是,在这种范式下,有两种可能的 GC 元方法用例是不确定的:

  1. 如果您有一个使用存储可收集值的局部变量的 GC 元方法怎么办。比如说,一个字符串、一个函数等。也就是说,你的 GC 元方法被定义为:

    local some_string = "string"
    function mt:__gc() --[[Do something with some_string]] end
    

    在这种情况下会发生什么?是否有可能some_string被收集?我知道如果在正常情况下正在收集元表所在的对象,那么这是不可能的。Lua 会保证 的值some_string会一直保持到 GC 函数本身被收集为止。

    但是由于所有对象都被 销毁lua_close,是否有可能在函数被销毁之前 GC 函数的上值被销毁?我认为不是(因为这可能会导致各种问题),但我正在寻找真正的答案,而不是我的想法。

  2. 我承认 #1 不太可能成为问题,因为它会在 GC 元方法中产生许多问题。然而,这是完全不同的事情:

    local some_string = "string"
    function mt:__gc() print(some_string) end
    

    这看起来像#1,但事实并非如此。为什么?因为它访问一个全局变量。即,print

    函数与存储的任何值之间没有直接关联print(与案例 1 不同,其中some_string显然是函数的上值)。因此,print在 Lua 状态关闭期间调用函数之前可能会被收集。

问题是:在 Lua 状态关闭期间,垃圾收集元方法是否可以安全地使用全局表中的任何内容(忽略对全局表的故意破坏的可能性)?print = nil或者,作为一般规则,他们是否应该始终明确地将他们接触到的任何函数或数据设为本地?这足以避免问题吗?

4

1 回答 1

4

可以从该__gc方法访问的任何数据都可以安全访问;这包括本地人和可访问的表,例如_G,其中包含print.

(未)加载的 C 库可能是个问题;这会影响 Lua 5.1,并在 Lua 5.2.1 中修复。请参阅“在库被卸载后终结器可能调用动态库中的函数”的补丁

于 2012-08-11T01:51:32.090 回答