[tolua++]tolua++中暴露對象給lua時,一定要把析構函數暴露給lua


題目不知道怎么取才好,但是意思很簡單:

如果你暴露一個復雜對象給Lua,實現類似於OO編程的話,那么也要把析構函數暴露給Lua.

否則的話,lua gc的時候,回收垃圾對象,沒有找到回收函數,就直接free掉了,這在C++中,是相當致命的.

 

tolua++中的tolua_cclass函數,用來注冊lua對象,

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

 同時會把最后的那個參數col,注冊到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");
        //....
	lua_pushcfunction(L,col);
        //....

 而發生gc的時候,class_gc_event函數會去在lua對象的元表里面找".collector"這個key,如果沒找到,就用default的析構,否則就用用戶提供的析構函數:

	top = lua_gettop(L);
	if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) /* make sure we collect correct type */
	{
		/*fprintf(stderr, "Found type!\n");*/
		/* get gc function */
		lua_pushliteral(L,".collector");
		lua_rawget(L,-2);           /* stack: gc umt mt collector */
		if (lua_isfunction(L,-1)) {
			/*fprintf(stderr, "Found .collector!\n");*/
		}
		else {
			lua_pop(L,1);
			/*fprintf(stderr, "Using default cleanup\n");*/
			lua_pushcfunction(L,tolua_default_collect);//這個是默認的析構函數
		}

		lua_pushvalue(L,1);         /* stack: gc umt mt collector u */
		lua_call(L,1,0);

 而默認的析構函數是C free的簡單封裝:

TOLUA_API int tolua_default_collect (lua_State* tolua_S)
{
 void* self = tolua_tousertype(tolua_S,1,0);
 free(self);
 return 0;
}

 

如果你通過tolua++注冊一個復雜類型給lua的話,析構函數不被調用,而直接調用了free,會發生很多未定義行為.

這就是在我們服務器中隱藏了超過兩年的一個Bug......


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM