Question

Is it possible that luabind checks, if a member function call to an exported class (object) is for a valid object?

lets assume that i have a Class called Actor exposed using luabind to lua. Im calling a lua function from C++ with an actor object as parameter. Now before the function finishes, a script write would put the actor object in a global lua reference to be accessed later.

Later on, the actor object is deleted from the C++ site, another function is called which tries to access the invalidated actor object (any method from it) - and obviously since it has been deleted, it results in a crash (access violation)

sample:

local myObjRef = nil

function doSomethingWithActor(actor)
 -- save, still valid object
 actor:Say("hello")
 myObjRef = actor
end

function calledAfterActorWasDeleted()
  --- will crash if the c++ object has been deleted meanwhile, works fine if it still exists
  myObjRef:Say("Crash...")
end

A NIL check doesnt help here, is this something that can be checked on luabinds site? The functions are executed using lua_pcall(....) and the stacktrace shows the error at luabinds call.hpp results = maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0);

If not, is there another solution how to make sure somebody who writes a script cannot create these issues?

Was it helpful?

Solution 2

I solved my issue the following way:

When im about to delete an object, i iterate through all lua functions from C++ (i have them in a list, they are bound to specific actor objects each). Then i inspect each upvalue (global/local vars accessable to a function) - then i compare the userdata pointer with my object im about to delete - if they match (and their classes) and NIL the upvalue. Optionally, i could just remove that offending function because it would not work well anymore anyway.

So the next the time the function is called, im just getting a soft lua error "trying to access xxx a nil value..." - no more access violations.

I know people would say "dont use lua_getupvalue/lua_setupvalue - they are only for debugging!" - but there is actually no documented or spoken side effect - and in my case its perfectly safe and works well - also there isnt the issue with left over proxy objects i could not delete.

OTHER TIPS

Now before the function finishes, a script write would put the actor object in a global lua reference to be accessed later.

That right there is where your problem is coming from. If you want Lua code to own the object (that is, preserve the existence of this object), then you need to use Luabind mechanics to tell Luabind that you want to do that. Otherwise, if you pass a pointer to some Lua function, Luabind will assume that the function will not be trying to gain ownership of it.

If you want ownership to be shared between Lua and Luabind, then you should wrap your objects in a boost::shared_ptr, and use Luabind's smart pointer mechanisms to do this.

You could also simply segregate your scripts better. If you have some script that operates on a particular actor, then that script and any functions it contains should be destroyed (ie: lose all references to it) along with the object. This requires proper coding discipline on the C++ side. It will also require that you use Lua environments to properly encapsulate each instance of a script, so that they can't sneak things out via globals. Lastly, you will need to have C++ maintain total control over when scripts are called and when they aren't.

Otherwise, ownership is something your scripters are simply going to have to know about and be careful of. They can't treat C++ parameters like any old Lua value.


If exercising disciplined programming practice is not possible or practical for you, then you will simply have to not pass Lua the actual C++ object. Instead, you need to pass Lua some proxy object, which is a reference to the original. boost::weak_ptr is a good example of such an object (though you wouldn't pass it exactly to Lua). The proxy would forward calls to the actual object. If the object has been deleted, the proxy would detect this and fail or do nothing or whatever.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top