#include <stdio.h> #include <string.h> #include <lua.hpp> #include <vector> static int Foo(lua_State *state); static const luaL_Reg LuaMyLib[] = { {"Foo", Foo} }; int main() { lua_State *state = luaL_newstate(); for(int i = 0; i < sizeof(LuaMyLib)/sizeof(LuaMyLib[0]); ++i) lua_register(state, LuaMyLib[i].name, LuaMyLib[i].func); const char *script = "Foo()"; if(0 != luaL_loadbuffer(state, script, strlen(script), 0)) { printf("%s\n", luaL_checkstring(state, -1)); lua_close(state); return 0; } if (0 != lua_pcall(state, 0, LUA_MULTRET, 0)) printf("%s\n", luaL_checkstring(state, -1)); lua_close(state); return 0; } int Foo(lua_State *L) { std::vector<char> buf; buf.resize(1000); //do something //... //shit happen! luaL_error(L, "Foo() error!"); return 0; }
廢話不多說,編譯後馬上用 valgrind 檢查...
疑!?在 luatest.cpp:35 出現了 memory leak?WTF!?這是為什麼呢?
因為呼叫 luaL_error() 處理錯誤時,Lua 使用 longjmp 產生類似 C++ exception 的效果脫離 VM,但 longjmp 並不會遵從 C++ stack unwinding 正確處理物件解構,也就是 luatest.cpp:34 產生的 vector 在離開 Foo() 時沒有呼叫 vector::~vector(),於是就遺失了 1000bytes!
要解決這個問題,用 C++ 的方式編譯 Lua 即可(把所有的 .c 改名為 .cpp),也由此可知 OS 幫我們安裝的 Lua lib 是 C 版本。
如果這個程式是放在 server side 整天不停執行,可預見的是在一段時間後一定會因為記憶體被消光導致系統崩潰,由此可見使用 valgrind 定期健檢的重要性!
沒有留言:
張貼留言