【问题标题】:C(++) and Lua Cleaning up MemoryC(++) 和 Lua 清理内存
【发布时间】:2013-04-12 17:42:58
【问题描述】:

我正在编写的应用程序中使用 Lua 的 C API,我正在尝试确定我使用它的方式是否留下了一些悬空指针(指向指针)。

假设我在 C++ 中有一个树状结构(实际上是类)

struct Leaf
{
  DoSomeLeafStuff();
  List<Leaf*> Children;
};

class Tree
{
public:
  Tree() { };
  virtual ~Tree() 
  { 
    /* iterate over Children and delete them */ 
  };

  void DoSomeTreeStuff();
  Leaf getRoot() const { return _root; }

private:
  Leaf* _root;
};

-- 假设 tree 已经创建并包含数据,我在 Lua 中这样使用它:

local root = tree:getRoot()
root:DoSomeLeafStuff()

现在我的 Lua 的 getRoot() 的 C 实现看起来像:

int LuaStuff::TreeGetRoot(lua_State* L)
{
  Tree* tree = *(Tree**)luaL_checkudata(L, 1, "MyStuff.Tree");

  if (tree != NULL && tree->getRoot() != NULL)
  {
    int size = sizeof(Leaf**);
    *((Leaf**)lua_newuserdata(L, size)) = tree->getRoot(); // allocate a pointer to a pointer
    lua_setmetatable(L, "MyStuff.Leaf");
  }
  else
  {
    lua_pushnil(L);
  }

  return 1;
}

在进行了一些故障排除后,我能够按预期释放我的 Tree 和 Leaf 对象。但到目前为止,我还没有找到一种令人信服的方式(至少对我而言)指针指针正在被清理。

我的问题是:我可以安全地假设 Lua 的 lua_newuserdata() 分配的内存被 Lua 的垃圾收集器自动清理了吗?

【问题讨论】:

标签: c++ memory-leaks lua


【解决方案1】:

我正在做类似的事情,在 Lua 中包装我自己的对象。我就是这样做的:

/*part of the functon, buffer_s is a structure holding pointer 
to the real object and some other fields (like who actually created the object)
*/
buffer_s* b = (buffer_s*) lua_newuserdata(L, sizeof(buffer_s));
b->ptr = new buffer;        
b->origin = FROM_LUA;       
luaL_getmetatable(L, "buffer");
lua_setmetatable(L, -2);

现在,在初始化库的同时,我也做了这样的事情:

luaL_newmetatable(L, "buffer");  //create metatable
lua_pushcfunction(L,lua_buffer_delete); //push Lua compatible "destructor"
lua_setfield(L, -2, "__gc");    //place it in the metatable under __gc index

lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");

luaL_register(L, NULL, maps_buffer_m);

现在 Lua 将在 free() (通过 GC)对象之前调用 __gc 元方法。您可以使用它来进行清理。

我是这样做的(部分功能):

if (b->origin == FROM_LUA)
{

     delete b->ptr;   //delete the object
     b->origin = PTR_INVALID;  //and mark it as invalid
     b->ptr = NULL;
     lua_newtable(L);
     lua_setmetatable(L, 1);        //set empty metatable, it's not buffer any more
     return 0;
}

希望对你有帮助:)

您可以考虑使用 tolua++ 或 swig 来自动执行绑定过程。它将节省大量时间,并且可能会以正确的方式处理对象的创建和删除。

【讨论】:

    【解决方案2】:

    我确实建议您使用一些Lua Wrapper Class。我一直在我们的项目中使用它,效果很好。它也使事情变得容易得多。 当你的 Lua 脚本结束时,使用这个类,包装器会破坏你正在使用的 Lua 状态来释放你的内存,以及你所有的用户数据。

    我也认为,如果你这样做:

    lua_close( mState );
    

    您的 userData 也将被清理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 2012-04-16
      • 2016-05-31
      • 2010-10-15
      • 1970-01-01
      • 2017-02-18
      相关资源
      最近更新 更多