首先要了解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無法定位。所以要注意不要去管理此類對象的內存釋放。