Lua 擁有自動垃圾回收(GC),理論上無傳統意義的內存洩露。此處的「洩露」指:對象已不再使用,但仍被外部引用(如全局表 _G、註冊表、metatable)導致 GC 無法回收。
例:函數內忘記 local 聲明表,導致其進入 _G,函數結束後引用仍存,GC 掃描到引用不回收。
Lua 支援 GC 的類型:string、table、function、full userdata、thread。它們的引用直接或間接保存在:
lua_state 對象(腳本本身)_G 全局表Registry 註冊表(debug.getregistry() 可訪問)global_state->mt 中的 metatable(debug.getmetatable() 可訪問)collectgarbage("collect"),遍歷上述根對象,記錄所有可達對象的初始快照。__mode = "k"/"v"/"kv"(弱引用),對應鍵/值不阻止 GC。upvalues(可為任意類型)與 environment(table)。將用戶創建的資源對象放入 __mode="v" 的弱表。運行後強制 GC,若弱表中對象仍存在,說明外部有強引用,疑似洩露。
三色標記法:
增量式執行,避免長時間停頓。
collectgarbage 常用選項| 選項 | 說明 |
|---|---|
"stop" | 停止 GC |
"restart" | 重啟 GC |
"collect" | 執行完整 GC 循環(默認) |
"count" | 返回當前內存使用(KB) |
"step" | 單步執行 GC,參數控制步長 |
"setpause" | 設置暫停倍率(默認 200,即內存翻倍觸發新循環) |
"setstepmul" | 設置步長倍率(默認 200,GC 速度為分配速度 2 倍) |
function testLocal()
collectgarbage("collect"); collectgarbage()
print("初始:", collectgarbage("count"))
local t = {} for i=1,5000 do t[i]={} end
print("創建後:", collectgarbage("count"))
end
function testGlobal()
collectgarbage("collect"); collectgarbage()
print("初始:", collectgarbage("count"))
g = {} for i=1,5000 do g[i]={} end
print("創建後:", collectgarbage("count"))
end
testLocal(); collectgarbage(); collectgarbage(); print("Local GC後:", collectgarbage("count"))
testGlobal(); collectgarbage(); collectgarbage(); print("Global GC後:", collectgarbage("count"))
-- Local 內存歸零,Global 內存殘留(洩露)