有关Lua状态关闭和垃圾收集元方法的规则

Nic*_*las 5 lua

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


当a lua_State关闭时lua_close,Lua文档说明所有对象都被删除了.并且它表示保证调用任何相关的垃圾收集元方法.

大.

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

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

    local some_string = "string"
    function mt:__gc() --[[Do something with some_string]] end
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下会发生什么?是否some_string可以收集?我知道如果在正常情况下正在收集metatable所在的对象,那么这是不可能的.Lua将保证some_string在GC函数本身被收集之前,其值将保持不变.

    但是由于所有对象都被破坏了lua_close,因此在函数出现之前,GC函数的upval可能会被破坏吗?我认为不是(因为这可能导致各种问题),但我正在寻找真正的答案,而不是我的想法.

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

    local some_string = "string"
    function mt:__gc() print(some_string) end
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

Dou*_*rie 4

可通过该方法访问的任何数据__gc都是安全的;这包括本地变量和可访问的表,例如_G包含print.

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