c++ 对象注册到lua 内存管理 tolua_cclass 中的内存释放 记一次闪退bug查找 此次闪退 可能发生在任何时机 难以查找

Deadly 提交于 2020-01-26 15:32:56

首先要了解lua的垃圾回收机制,lua中的垃圾回收机制是每隔一段时间清除不再被引用的对象,也就是说一个对象如果不再被使用就会在下次的gc中被回收掉,这个不需要我们管理,是lua中的自动回收机制。接下来看一下c++注册到lua的接口:

TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col)

{

    char cname[128] = "const ";

    char cbase[128] = "const ";

    strncat(cname,name,120);

    strncat(cbase,base,120);

 

    mapinheritance(L,name,base);

    mapinheritance(L,cname,name);

 

    mapsuper(L,cname,cbase);

    mapsuper(L,name,base);

 

    lua_pushstring(L,lname);

    push_collector(L, name, col);

    /*

    luaL_getmetatable(L,name);

    lua_pushstring(L,".collector");

    lua_pushcfunction(L,col);

 

    lua_rawset(L,-3);

    */

 

//---- create a new class table, set it's metatable, and assign it to module

    lua_newtable(L);                    // stack: module lname table

    luaL_getmetatable(L,name);          // stack: module lname table mt

    lua_setmetatable(L, -2);            // stack: module lname table

    //Use a key named ".isclass" to be a flag of class_table

    lua_pushliteral(L, ".isclass");

    lua_pushboolean(L, 1);

    lua_rawset(L, -3);                  // stack: module lname table

    lua_rawset(L, -3);                  // stack: module

//---- by SunLightJuly, 2014.6.5

 

    /* now we also need to store the collector table for the const

       instances of the class */

    push_collector(L, cname, col);

    /*

    luaL_getmetatable(L,cname);

    lua_pushstring(L,".collector");

    lua_pushcfunction(L,col);

    lua_rawset(L,-3);

    lua_pop(L,1);

    */

}

 

在c++对象注册到lua时一共有五个参数,这里主要说明最后一个参数,在上边的接口中第六行的函数实现如下:

static void push_collector(lua_State* L, const char* type, lua_CFunction col) {

 

    /* push collector function, but only if it's not NULL, or if there's no

       collector already */

    if (!col) return;

    luaL_getmetatable(L,type);

    lua_pushstring(L,".collector");

    /*

    if (!col) {

        lua_pushvalue(L, -1);

        lua_rawget(L, -3);

        if (!lua_isnil(L, -1)) {

            lua_pop(L, 3);

            return;

        };

        lua_pop(L, 1);

    };

    //    */

    lua_pushcfunction(L,col);

 

    lua_rawset(L,-3);

    lua_pop(L, 1);

};

lua中垃圾回收是在程序发生gc的时候,class_gc_event函数会去在lua对象的元表里面找".collector"这个key,如果没找到,就用default的析构,否则就用用户提供的析构函数。也就是这一段代码把最后的那个参数。此类对象则不需要用户自己再去管理内存的释放。否则若用户先释放了该对象,在gc中再次释放的时候便会报错。因为gc发生的时机可能在每一个时间,所以就会出现程序一直闪退,但是每次闪退的点都不一样,导致bug无法定位。所以要注意不要去管理此类对象的内存释放。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!