When lua gets pointers for user objects (via the lua_pushuserdata call)
does it do reference counting on the object it creates with the pointer,
or on the pointer itself? For example, if createobj() is a lua function
that returns a user data object, then what does the following code do?
obj1=createobj() -- statement 1
obj2=obj1 -- statement 2
obj1=nil -- statement 3
collectgarbage() -- statement 4
obj2=nil -- statement 5
collectgarbage() -- statement 6
Does lua collect the object created in statement 1 in statement 4 or 6?
If lua does reference counting on the object that contains the user pointer
and not the pointer itself, then the garbage collect tag method will be
called in statement 4. If the actual user data pointer is reference counted,
then it will not be garbage collected until the last instance of the
pointer, or obj2, is destroyed, so that the garbage collect tag method
should be called in statement 6.
I am interested in this for two reasons. I have written a set of classes
for lua that manipulate images and I would like to ensure that a freed
pointer is never used by lua, and that once a pointer is no longer referenced
it is always freed. Therefore, I have a garbage collect tag method, which
I hope is called only when the last instance of the pointer I created the
user data object with is overwritten.
Also, it seems to me examining the iolib.c library that there is other
potential to have bad pointers available. For example, consider this code:
filepointer=writeto("myfile") -- statement 7
write("stuff\n") -- statement 8
temporary=filepointer -- statement 9
writeto() -- statement 10
_OUTPUT=temporary -- statement 11
write("this will screw it up") -- statement 12
writeto() -- statement 13
The file and its FILE * object are created with statement 7, and statement 10
will close the file. However, the user data pointer has been stored in
another variable "temporary." But since the file has been closed, the FILE *
it points to is invalid, but is still used. Am I correct in my analysis
of what would happen in this program?
Perhaps it would be better to make the close file command the garbage
collect tag method in the iolib.c library, to ensure that the file is
never closed before lua loses all references to it. Especially in a
multithreaded system, where objects could be shared between threads,
a system that ensures that bad pointers are never used would be very
beneficial, I would think.
At any rate, lua is great for our image processing code and experiment.
Thanks for the great, simple language.
Lua does not use reference counting for garbage collector, but
mark-and-sweep (but that is not the point...). Userdata (that is, C pointers)
are considered objects and Lua, and the important point is: A userdata
is collected (and therefore has its "gc" tag method called) *only* when
there are no more references to that userdata inside Lua. In your particular
example, the userdata will be collected in statement 6.
> Also, it seems to me examining the iolib.c library that there is other
> potential to have bad pointers available. For example, consider this code:
In fact, there is a problem here, but to me this seems a different stuff.
The problem here is that we do not use "gc" to control files, but an explicit
"close" (written as <writeto()>) function. Therefore, there is always this
problem of writing to a file which has been closed. Notice that your example
could be simplified to:
write("this will screw it up")
(that is, there is no need of a temporary to screw it up :-).
One way to solve that would be to have files closed only when they are
garbage collected, but that can take too long in some apps (that is, you may
run out of file descriptors before the garbage collector is activated). The
other way is to change the tag of the userdata when we close it, so any
attempt to write or read it after that will trigger an error.