In my Lua C++ integration (Lua 5.3.4) I'm having problems during Lua runtime shutdown. I have an std::unique_ptr which holds the Lua State and I save a collection of states into a std::list which lies in global scope:
using lua_state = std::unique_ptr<lua_State, decltype(lua_close) *>;
std::list<lua_state> ls;
int main(int argc, char** argv)
{
for (int script = 0; script < 10; ++script)
{
const auto L = ls.emplace_back(luaL_newstate(), lua_close).get();
if (luaL_dofile(L, "test.lua") == 0)
{
for (int value = 0; value < 50; ++value)
{
auto name = ("TEST" + std::to_string(value));
lua_pushnumber(L, value);
lua_setglobal(L, name.c_str());
}
}
}
// do things with each script
return 0;
}
I load a bunch of Lua scripts and set a collecion of global values1, when the program finishes, the ls list is destroyed hence lua_close is called and it ends doing something that looks like a double free.
Call stack
app.exe!l_alloc(void * ud, void * ptr, unsigned int osize, unsigned int nsize)
app.exe!luaM_realloc_(lua_State * L, void * block, unsigned int osize, unsigned int nsize)
app.exe!freestack(lua_State * L)
app.exe!close_state(lua_State * L)
app.exe!lua_close(lua_State * L)
app.exe!std::unique_ptr<lua_State,void (__cdecl*)(lua_State *)>::~unique_ptr<lua_State,void (__cdecl*)(lua_State *)>()
In the l_alloc function, an exception is thrown in free call:
lauxlib.c Lua 5.3.4
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
free(ptr);
// ^^^^^^^^^^ <--- HEAP[app.exe]: Invalid address specified to RtlValidateHeap( 00080000, 000B0D90 )
return NULL;
}
else
return realloc(ptr, nsize);
}
If I set a breakpoint in the lua_close function and check the state of the stack (lua_gettop) I get a stack of size -6 and checking the types of the values held in the stack I get:
lua_typename(L, lua_type(L, -1)) "thread"
lua_typename(L, lua_type(L, -2)) "thread"
lua_typename(L, lua_type(L, -3)) "thread"
lua_typename(L, lua_type(L, -4)) "nil"
lua_typename(L, lua_type(L, -5)) "nil"
lua_typename(L, lua_type(L, -6)) "nil"
My guess is that the scripts have some tasks running (even if I don't call any script function from C++), maybe some cleanup tasks and this tasks interfere with the normal shutdown.
Any hint about why is this happening and how to solve it?
1The code is way more complicated, this is just an example.