lua-users home
lua-l archive

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


It was thus said that the Great Francisco Olarte once stated:
> Hello everybody.
> 
> I'm trying (unsuccessfully) to see in the docs if a function argument
> can be collected during a pcall. What I mean is:
> 
> 0.- I push a function.
> 1.- I push a userdata object as argument.
> 2.- I do lua_pcall(L,1,1,0) ( Or lua_call or other similar stuff ).
> 
> Can my object be garbage collected before returning from pcall (i.e.,
> if the function sets its argument to nil and then calls collectgarbage
> ).?
> 
> I need to know this because the object I push has a __gc method which
> destroys it, and I need to access some data inside it just after
> return.
> 
> ( I know I can keep it alive by storing it in the registry or dupping
> it or anything similar ).

  I've gone back up to the first message basically because I don't know
where else to insert this into the chain of emails.  So, right back at the
start.

  I'm looking at the Lua manual for lua_pcall(), and past the function
protocol, all the way to the right, is this notation:

	[-(nargs + 1),+(nresults|1),-]

This tells me that all the parameters, plus the function itself, is popped
from the Lua stack, and any results from the called function are pushed onto
the stack (or an error---this is lua_pcall() after all).  Since you create a
userdata and pass it right to the function, once that function returns,
*even if it didn't explicitely nil out that parameter* is it no longer
accessible to Lua and thus, subject to garbage collection.

  The same applies to lua_call(), lua_callk() and lua_pcallk()---the calling
parameters are popped off the stack during the process of the call.

  That you may still have access to it via a pointer from lua_newuserdata()
is beside the point---how you constructed the function call means that once
said call is done, that particular piece of datum is no longer accessible
according to the Lua documentation.  It's somewhat similar to this bit of C
code:

	int *p = malloc(sizeof(int));
	if (p)
	{
	  free(p);
	  *p = 3;
	}

  It's a violation of the C standard but it will still probably work (only
the issue may be spelled out a bit better in the C standard).

  -spc