将Raylib的GetMousePosition()绑定到Lua引发内存泄漏[Lua C API]
问题:Lua绑定GetMousePosition时频繁创建表导致内存波动
我通过Lua C API实现了lua_getmouseposition函数,绑定Raylib的GetMousePosition()获取鼠标位置,将结果存入Vector2后转成Lua表返回。但Lua脚本循环调用时,每次都会生成新表,内存每秒涨45-95KB,GC回收后又快速回升,频繁触发GC。试过lua_pop和MemFree()没用,其他Raylib函数绑定正常,求修改方案,避免频繁创建新表。
绑定函数原代码:
static int lua_getmouseposition(lua_State *L) { Vector2 *mousePosition = MemAlloc(sizeof(Vector2)); if (mousePosition == NULL) { MemFree(mousePosition); return luaL_error(L, " GetMousePos error: out of memory \n"); } *mousePosition = GetMousePosition(); lua_newtable(L); // push x value to the table lua_pushstring(L, "x"); lua_pushnumber(L, mousePosition->x); lua_settable(L, -3); // push y value to the table lua_pushstring(L, "y"); lua_pushnumber(L, mousePosition->y); lua_settable(L, -3); lua_pop(L, -3); MemFree(mousePosition); return 1; }
Lua脚本原代码:
while not WinShouldClose() do begin() cls(0, 0, 0) -- clear the screen, with a certain color pos = GetMousePos() -- draw the player (rectangle/square) DrawImage(sprite, pos1.x, pos1.y) playerInput() displayInfo() stop() end
解决方案
方案1:复用全局缓存表
在Lua全局环境中维护一个固定的鼠标位置表,每次调用仅更新表内的x、y值,彻底避免频繁创建新表。
修改后的C代码:
static int lua_getmouseposition(lua_State *L) { // 尝试获取全局环境中的缓存表 lua_getglobal(L, "__mouse_pos_cache"); if (!lua_istable(L, -1)) { lua_pop(L, 1); // 弹出栈上的非表值 lua_newtable(L); lua_pushvalue(L, -1); lua_setglobal(L, "__mouse_pos_cache"); // 将新表存入全局环境 } // 直接用栈上变量存储鼠标位置,无需动态分配 Vector2 mousePosition = GetMousePosition(); // 更新表内的x、y值 lua_pushstring(L, "x"); lua_pushnumber(L, mousePosition.x); lua_settable(L, -3); lua_pushstring(L, "y"); lua_pushnumber(L, mousePosition.y); lua_settable(L, -3); // 返回复用的缓存表 return 1; }
方案2:让Lua脚本传入表复用
如果不想依赖全局表,可让Lua脚本提前创建表并传入函数,函数仅更新该表的内容。
修改后的C代码:
static int lua_getmouseposition(lua_State *L) { // 检查是否传入了表参数,无参数则创建新表(兼容原有调用逻辑) int create_new = 0; if (!lua_istable(L, 1)) { lua_newtable(L); create_new = 1; } else { lua_pushvalue(L, 1); // 将传入的表推到栈顶 } Vector2 mousePosition = GetMousePosition(); // 更新表内容 lua_pushstring(L, "x"); lua_pushnumber(L, mousePosition.x); lua_settable(L, -3); lua_pushstring(L, "y"); lua_pushnumber(L, mousePosition.y); lua_settable(L, -3); // 返回表(新创建/传入的表) return 1; }
对应的Lua脚本修改:
-- 提前创建一次表,后续循环复用 local pos = {} while not WinShouldClose() do begin() cls(0, 0, 0) GetMousePos(pos) -- 传入已有表更新内容 DrawImage(sprite, pos.x, pos.y) playerInput() displayInfo() stop() end
原代码问题分析
lua_pop(L, -3)是错误用法:lua_pop的第二个参数是弹出数量,而非栈索引,这会导致返回的表被错误弹出,引发内存异常。- 动态分配
Vector2完全冗余:直接用栈上变量即可完成存储,无需额外的MemAlloc/MemFree操作。
内容的提问来源于stack exchange,提问作者Planebagel
相关产品推荐
相关产品推荐

