1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #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 定期健檢的重要性!
沒有留言:
張貼留言