Why one job and one crash?

It drove me crazy for more than a week. Below are two snippets of Lua code from a robot player in a Bitfighter game (written in C ++, using the LuaWrapper variant for binding).

When I first run the Lua script, they work exactly as expected. But after several minutes of intensive creation of the object and its destruction, option 2 stops working and gives me the following error:

robot.lua:253: attempt to call missing or unknown method 'getEnergy' (a nil value)

In my eyes they should function the same. Who can explain the difference?

Notes: target is (heavy) user information representing a C ++ object. getEnergy and getHealth are correctly registered C ++ functions. I can easily reproduce this different behavior. This is Lua 5.1 using luavec mod.

Option 1 - always works

local mt = getmetatable(target)
local pow = mt.getEnergy(target) + mt.getHealth(target)

Option 2 - starts crashing after the script runs for an arbitrary amount of time

 local pow = target:getEnergy() + target:getHealth()
+4
source share
3 answers

To keep track of what happens when it stops working, you can wrap the call in pcalland find out what happened to the value target:

local ok, res = pcall(function() return target:getEnergy() + target:getHealth() end)
if not ok then
  local s = "Invalid target value: "..tostring(target).." "..type(target).."\n"
  for k, v in pairs(target) do s = s.."target "..tostring(k).." "..tostring(v).."\n" end
  for k, v in pairs(getmetatable(target)) do s = s.."meta "..tostring(k).." "..tostring(v).."\n" end
  -- add anything else that helps you figure out what happened to target
  error(res..s)
end
local pow = res
+5
source

I strongly suspect that the problem is that you have a class or structure like this:

struct Foo
{
    Bar bar;
    // Other fields follow
}

And you set both Foo and Bar in Lua through LuaWrapper. The important thing here is that bar- this is the first field in your structure Foo. In addition, you may have a class that inherits from some other base class, and both the derived and base classes are exposed by LuaWrapper.

LuaWrapper , , (, , Lua). . , , , Foo Bar , , , LuaWrapper .

, . , , metatable, , , , metatable .

, , . LuaWrapper , , .

+1

When you say that it stops working at some stage, but it works fine before that ... Maybe you overwrite the .getEnergy function anywhere at runtime? Maybe you use foo.getEnergy = nilinstead foo.getEnergy == nilsomewhere? It looks like it might be late initialization went wrong :)

0
source

All Articles