如何查找跟踪LuaJIT中某个时间点GC掉的userdata?

我用LuaJIT编写了一个应用程序,使用了第三方GUI框架(基于FFI)+一些自定义的FFI调用。应用程序在运行后不久会突然失去部分功能,我非常自信是由于一些未固定的对象被GC掉所致。我假设它们只从C世界中引用,所以Lua GC认为它们未被引用,可以释放它们。问题是,我不知道Lua侧的哪个众多的userdata未被引用(未固定)?

为了确认我的理论,我以GC禁用的方式运行了应用程序,通过以下方式进行:

collectgarbage 'stop'

通过这行代码,应用程序可以完美地运行得很久,直到之前出现故障的点。显然,这是一个丑陋的解决方法,我非常希望GC保持启用状态,应用程序仍然可以正确运行...

我想找出哪个未固定的对象(userdata,我假设)被GC了,这样我就可以在Lua侧正确固定它,以防止它被过早地GC。因此,我的问题是:

(如何)跟踪哪些userdata对象在应用程序失去功能时被收集了?

一个问题是,据我所知,LuaJIT FFI已经分配了自定义的__gc处理程序,因此我无法添加自己的,因为每个对象只能有一个。而且,这个框架对于我来说太大了,我无法尝试在每个可能的地方都添加__gc。此外,通过将一些变量的“local”移除 - 使它们成为“_G”的一部分,我已经从代码中的“最明显的嫌疑地点”中排除了一些变量,因此我假设它们不可GC。 (或者这不够吗?)

1 具体来说,WinAPI。

点赞
用户98528
用户98528

目前,我已经为我的一些对象添加了一些 ffi.gc() 处理程序(打印一些易于识别的全部大写字母消息),然后添加了一些急切的 collectgarbage() 调用来尝试尽快触发该问题:

ffi.gc(foo, function()
    print '\n\nGC FOO !!!\n\n'
end)

[...]

collectgarbage()

事实上,这暴露出了一些我没有预期到的 GC 问题。具体而言,它让我发现了 luajit 的 FFI 文档中的一条注释,这对我的情况肯定是相关的:

请注意,[C] 指针[...]不会被垃圾收集器跟踪。因此,例如,如果您将 cdata 数组分配给指针,则必须在指针仍在使用时将保存数组的 cdata 对象[在 Lua 中]保持活动状态。

2017-03-20 22:25:42