miko wrote:leiradel wrote:miko wrote:Clearly a memory leak somewhere
I'm pretty sure there's no memory leak, it's just the way Lua handles user data.
Youare right in the sense you have described. It is a "leak" from the lua point of view.
The "workaround" is to put
or
in love.update() - this fixes problem of memory usage (and crashing) for me.
It's not really a leak from either C++ or Lua side, it's just regular memory management. See
this thread on the Lua mailing list for a great discussion about the subject and the pros/cons of this workaround.
One of the proposed solution is to use custom allocators on the C/C++ side to make Lua aware of the total memory used:
Code: Select all
void* my_malloc(size_t sz, lua_State* L)
{
void* p = lua_newuserdata(L, sz);
lua_pushlightuserdata(L, p);
lua_insert(L, -2);
lua_settable(L, LUA_REGISTRYINDEX);
return p;
}
void my_free(void* p, lua_State* L)
{
lua_pushlightuserdata(L, p);
lua_pushnil(L);
lua_settable(L, LUA_REGISTRYINDEX);
}
and change code to always allocate and free memory using those functions. C++ instances can use the placement new on the pointer returned by my_malloc. The drawbacks of this workaround are:
- It's slower than malloc/free because you're asking Lua to allocate/free memory (which in turn calls malloc/free) and because of the extra handling to put/remove the user data into/from the Lua registry. But since malloc is already slow, it might not be an issue.
- There's no realloc, if you need to increase/decrease the size of the memory a pointer points to you'll have to allocate memory, copy the contents of the old pointer to the new pointer and free the old pointer. Of course it's just what realloc does when the current block cannot be made larger.
- It does not solve the problem if the allocation is made by an external library, unless you patch it to use my_alloc/my_free
Lua 5.2 added an emergency garbage collector. The documentation was not updated, but I think that what it does is to make it safe to execute the garbage collector inside your lua_Alloc function if the allocation failed so that the GC frees some memory and you can retry your allocation. I don't think this will solve this particular problem since page swaps will begin much before an allocation fails, probably making things so slow you'll have to kill LÖVE. But taking note of actual memory usage in your lua_Alloc and limiting it in some reasonable way may solve it.
Cheers,
Andre