背景
我在游戏中与 Watusimoto 合作 Bitfighter .我们使用 LuaWrapper 的变体将我们的 c++ 对象与游戏中的 Lua 对象连接起来。我们还使用了一个名为 lua-vec 的 Lua 变体。加速 vector 运算。
一段时间以来,我们一直致力于解决一个未能解决的错误。将发生随机崩溃,表明元表已损坏。参见 here对于 Watusimoto 关于此问题的帖子。我不确定这是因为损坏的元表,并且看到了一些我想在这里询问的非常奇怪的行为。
问题表现
例如,我们创建一个对象并将其添加到如下级别:
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
的元表。
然而,这太疯狂了,当它失败并打印出元表时,元表完全它应该如何(正确的 addItem
调用和一切) .如果我在脚本加载时打印 levelgen
的元表,并且当它使用上面的 pcall
失败时,它们是相同的,每个调用和指向 userdata 的指针都是相同的,并且应该如此是。
就好像 levelgen
的元表随机自发地消失了。
谁知道发生了什么事?
谢谢
注意:只有 levelgen
对象不会发生这种情况。例如,它也发生在上面提到的 TestItem
对象上。事实上,同样的代码在我的计算机上的 levelgen:addItem(t)
行崩溃了,但在另一位开发人员的计算机上的 t:setText("hello")
行崩溃了具有相同的错误消息 missing or unknown method 'setText' (a nil value)
最佳答案
与任何谜团一样,您需要一层一层地揭开它。我建议执行 Lua 正在执行的相同步骤,并尝试检测所采用的路径与您的预期有何不同:
getmetatable(levelgen).__index
返回什么?如果是表格,则检查其内容是否有 addItem
。如果它是一个函数,则尝试使用 (table, "addItem")
调用它并查看它返回什么。
检查 getmetatable
在调用前后(或失败时)是否返回对同一对象的引用。
调用是否经过多个级别的元表间接寻址?如果是这样,请尝试通过显式调用遵循相同的路径并查看差异在哪里。
如果没有其他引用,您是否使用了可能导致值消失的弱
键?
能否在检测失败时提供一个“默认”值,以后继续看是否再次“找到”这个方法?或者当它坏了,之后的每个电话都坏了?
如果您为 addItem 保存一个正确的值并在检测到它损坏时“修复”它会怎么样?
如果您只是简单地处理错误(如您所做的那样)并调用它 10 次会怎么样?它会至少显示一次有效结果吗(在失败之后)? 100次?如果你一直调用同一个方法,当它起作用时,它会失败吗?这可能会帮助您找出更可重现的错误。
我不熟悉 LuaWrapper,无法提供更具体的问题,但如果我是你,我会采取这些步骤。
关于c++ - Lua、C++ 和消失的元表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14916985/