davidsiaw / luacppinterface

A Simple C++ Interface to Lua
MIT License
167 stars 27 forks source link

Error in releasing memory #19

Closed zangobot closed 9 years ago

zangobot commented 9 years ago

I'm trying to destroy an object which was binded to a LuaUserdata.

LuaUserdata object = _lua.CreateUserdata(this);

My program crash when I close it, saying that it can't free a non-allocated pointer. I'm sure the problem is in the LuaUserdata: if I remove that line of code there is no crash.

davidsiaw commented 9 years ago

Hmm. Can you provide more context?

zangobot commented 9 years ago

Of course! :D I create that LuaUserdata, with some bindings:

LuaUserdata<Agent> object = _lua.CreateUserdata(this);
auto global = _lua.GetGlobalEnvironment();
global.Set(name, object);
object.Bind("moveLeft", &Agent::moveLeft);
object.Bind("wait", &Agent::wait);

The object variable is not used anymore. Now it's time to destroy what was created. My object lives in a Scene, which call this lines of code when destroyed:

 if(_back != nullptr)
        delete _back;
    if(_man != nullptr)
        delete _man;

_man has that method I pasted before. This code produces this error when I close the game: malloc: *\ error for object 0x10061bab0: pointer being freed was not allocated I was a bit confused, so I tried to remove something in order to find the bug. Deleting the destruction of the _man variable resolves the issue. I thought was an error in my destructor, but I tried to remove the binding from Lua: no more crash.

EDIT: This is the guilty line of code:

return CreateUserdata<TYPE>(data, [](TYPE* data){ delete data; });
davidsiaw commented 9 years ago

Okay, I think I understand now. Basically, the Lua object assumes ownership of a the pointer you give to CreateUserdata. This is because it wraps it. This means that when you try and delete the LuaUserdata, it will go ahead and delete the object you created.

In other words, since your Agent object contains the LuaUserdata

  1. delete Agent calls delete LuaUserdata
  2. LuaUserdata calls delete on the Agent
  3. Agent pointer is freed
  4. LuaUserdata is freed
  5. delete attempts to free Agent's pointer but fails.

Read the Ownership section of the README.

zangobot commented 9 years ago

Ok, thank you! :+1: Basically I have to destroy the LuaUserdata in order to destroy my object?

davidsiaw commented 9 years ago

Yes. Only keep a reference to the LuaUserdata, since it owns the agent. Free the LuaUserdata object and not the agent