我在游戏Bitfighter上使用Watusimoto.我们使用LuaWrapper的变体将我们的c对象与游戏中的Lua对象连接起来.我们还使用了一个名为lua-vec的Lua变体来加速向量运算.
我们一直在努力解决一段时间没有找到错误的bug.将发生随机崩溃,表明腐败的元数据.有关Watusimoto的帖子,请参阅here.我不确定这是因为一个腐败的metatable,并且看到了一些我想在这里问的非常奇怪的行为.
问题表现形式
作为一个例子,我们创建一个对象并将其添加到这样的级别:
t = TextItem.new() t:setText("hello") levelgen:addItem(t)
但是,游戏有时会(并非总是)崩溃.出错:
attempt to call missing or unknown method 'addItem' (a nil value)
使用上面提到的Watusimoto帖子中给出的建议,我已将最后一行更改为以下内容:
local ok, res = pcall(function() levelgen:addItem(t) end) if not ok then local s = "Invalid levelgen value: "..tostring(levelgen).." "..type(levelgen).."\n" for k, v in pairs(getmetatable(levelgen)) do s = s.."meta "..tostring(k).." "..tostring(v).."\n" end error(res..s) end
如果错误地从中调用方法,则会打印出levelgen的metatable.
然而,这很疯狂,当它失败并打印出metatable时,metatable正是它应该是如何(使用正确的addItem调用和所有内容).如果我在脚本加载时打印levelgen的metatable,并且当它使用上面的pcall失败时,它们是相同的,每个调用和指向userdata的指针都应该是相同的.
似乎levelgen的metatable随机地自发消失.
有谁会知道发生了什么?
谢谢
注意:只有levelgen对象才会发生这种情况.例如,它也发生在上面提到的TestItem对象上.实际上,同样的代码在我的计算机上崩溃了行levelgen:addItem(t)但在另一个开发人员的计算机上崩溃了,行t:setText(“hello”)缺少相同的错误消息或者未知方法’setText'(a零值)
与任何谜团一样,你需要逐层剥离它.我建议按照Lua的相同步骤进行操作,并尝试检测路径偏离预期的位置:getmetatable(levelgen).__ index返回什么?如果是表,则检查其内容是否为addItem.如果它是一个函数,那么尝试用(table,“addItem”)调用它并查看它返回的内容.
检查getmetatable是否在调用之前和之后(或失败时)返回对同一对象的引用.
是否有几个级别的metatable间接呼叫正在通过?如果是这样,请尝试使用显式调用遵循相同的路径,并查看差异的位置.
您是否使用弱键,如果没有其他引用,可能会导致值消失?
当您检测到它失败并继续查看它是否“稍后”再次“找到”此方法时,您能提供“默认”值吗?或者当它被打破时,它之后的每次通话都会被打破?
如果为addItem保存一个正确的值并在检测到它时被“修复”怎么办?
如果您只是处理错误(就像您一样)并将其调用10次怎么办?它会至少显示一次有效结果(失败后)吗? 100次?如果你在工作时继续调用相同的方法,它会失败吗?这可以帮助您提出更可重现的错误.
我不熟悉LuaWrapper提供更具体的问题,但如果我是你,这些是我要采取的步骤.