Lua中一個lua_State就對應一個lua stack,通常情況下一個lua stack就足夠了,由此便產生了與C/C++不同的地方:在C/C++中每個函數調用都會有自己對應的stack,在函數調用完成之后,便將其釋放掉,因而不需要擔心stack會無限制地生長下去;而在C/C++中使用Lua,由于所有的操作都基于同一個stack,因此需要程序員自己在代碼中做stack的清理工作。
Lua提供了一對API來幫助程序員操縱stack:lua_gettop和lua_settop。下面給出兩種清理棧的方法:
1)為每個操作Lua棧的C/C++函數添加一個棧頂位置參數。在調用該函數時將lua_gettop的結果作為參數傳遞,在函數調用結束時使用lua_settop以傳入的棧頂位置作為參數恢復調用前的棧頂位置。CEGUI中的script module便采用此方法,下面摘錄相關代碼:

/**//*************************************************************************
Execute script code string
*************************************************************************/
void LuaScriptModule::executeString(const String& str)


{
int top = lua_gettop(d_state);

executeString_impl(str, initErrorHandlerFunc(), top);
cleanupErrorHandlerFunc();
}

void LuaScriptModule::executeString_impl(const String& str, const int err_idx,
const int top)


{
// load code into lua and call it
int error = luaL_loadbuffer(d_state, str.c_str(), str.length(), str.c_str()) ||
lua_pcall(d_state, 0, 0, err_idx);

// handle errors
if (error)

{
String errMsg = lua_tostring(d_state,-1);
lua_settop(d_state,top);
throw ScriptException("Unable to execute Lua script string: '" +
str + "'\n\n" + errMsg + "\n");
}

lua_settop(d_state,top);
}
2)利用局部變量的創建與銷毀來自動實現stack清理。下面為局部變量的類型
struct LuaStackAutoPopup

{
lua_State* mBackupLS;;
int mPos;
LuaStackAutoPopup( lua_State* vpSL )

{
mPos = lua_gettop( vpSL );
mBackupLS = vpSL;
}

void Popup( )

{
lua_settop( mBackupLS,mPos );
mBackupLS = NULL;
}

~LuaStackAutoPopup( )

{
if( mBackupLS )
lua_settop( mBackupLS,mPos );
}
};
利用此機制,改造方法1中的executeString:

/**//*************************************************************************
Execute script code string
*************************************************************************/
void LuaScriptModule::executeString(const String& str)


{
LuaStackAutoPopup stack(d_state);

executeString_impl(str, initErrorHandlerFunc());
cleanupErrorHandlerFunc();
}

void LuaScriptModule::executeString_impl(const String& str, const int err_idx)


{
// load code into lua and call it
int error = luaL_loadbuffer(d_state, str.c_str(), str.length(), str.c_str()) ||
lua_pcall(d_state, 0, 0, err_idx);

// handle errors
if (error)

{
String errMsg = lua_tostring(d_state,-1);
throw ScriptException("Unable to execute Lua script string: '" +
str + "'\n\n" + errMsg + "\n");
}
}