lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Jerome Vuarand wrote:
> Saravanan Palanichami wrote:
>>   I seem to have a problem with memory in lua ...

> With the above code, you don't make sure that the stack size is balanced
> (that is it doesn't necessarily have the same size when entering the
> RunString function and when leaving it). If your Command snippet is
> returning multiple values, LUA_MULTRET let them on the stack, and your
> stack simply grow (the GC cannot collect things on the stack). So make
> sure you clean your stack properly according to your Command return
> values (either in RunString or in the function calling RunString).

That's undoubtedly the problem. If that function is called repeatedly
then the stack will slowly expand: each loop adds the error function
(and you should really check to make sure that function is a function
and not, for example, nil), and then either an error string or the
return value(s) from the chunk. My guess is that the stack is filling
up with multiple copies of the error function.

The LUA_MULTRET lua_pcall will avoid stack overflow, although this is
not really documented and in my opinion the code is incorrect: if
the intention was to allow the stack to expand, it ought to call
lua_checkstack() during the loop.

The observed behaviour -- that Lua does an allocation every 10 or 20
iterations -- is completely consistent with Lua deciding to realloc
the stack every so often, which it will do because a MULTRET call
does an implicit lua_checkstack().

> The other possible leak can come from an eventual side effect of your
> Command. If the command allocates data in the globals table (that is if
> it creates entries in _G, or any table in _G, or in any table in one of
> these tables, etc.), then that data is not collectible, and you have a
> leak.

I don't know that I would call that a leak, necessarily. If the chunk
defines a new global, then that will require an allocation, but that's
more or less normal operation. When the lua_State is eventually closed,
the memory will be reclaimed. If the chunk simply redefines an existing
global, then the old value will become collectable.

That might be happening as well, without any indication of memory
consumption increasing, which is why I wouldn't say it's a memory leak.
As I said, the most likely explanation of the observed behaviour
(periodic allocations) is that it represents a stack expansion. I'd
expect the periods to increase exponentially -- 10, 20, 40, ...