Stefano Cossu
unread,Jul 14, 2026, 5:27:11 PM (10 days ago) Jul 14Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to lua-l
Hello,
I have a Lua C module defining two different userdata types, one is
called a Dataset and the other a TermSet. Both can be used and
garbage-collected independently. A Dataset object has a TermSet as a
"gr" attribute. I am setting this term set as a uservalue for the dataset.
The problem is that if I access the term set from the dataset, it gets
garbage collected when it falls out of scope, and then, when the dataset
is garbage collected too, it calls a free function that attempts to free
the term set that was already freed, resulting in a double-free error.
This is the function used for creating the object:
// Called by dataset factories
int dataset_to_udata (lua_State *L, VOLK_Store *store)
{
VOLK_Dataset **dsp = lua_newuserdatauv (L, sizeof (*dsp), 2);
luaL_getmetatable (L, "volksdata.Dataset");
lua_setmetatable (L, -2);
VOLK_Dataset *ds = VOLK_dataset_new (store);
LUA_NLCHECK (ds, "Error creating dataset.");
*dsp = ds;
// Set store uservalue.
lua_pushvalue(L, 1);
lua_setiuservalue (L, -2, 1);
// Set gr uservalue.
VOLK_TermSet **ts_p = lua_newuserdata (L, sizeof (*ts_p));
LUA_NLCHECK (ts_p, "Error allocating memory for term set.");
luaL_getmetatable (L, "volksdata.TermSet");
lua_setmetatable (L, -2);
lua_setiuservalue (L, -2, 2);
return 1;
}
And the access function:
static int
get_graphs (lua_State *L)
{
(void) check_dataset (L, 1);
lua_getiuservalue (L, 1, 2);
return 1;
}
I thought that setting the uservalue would prevent the term set from
being garbage collected when it falls out of scope, but I guess that it
still gets garbage collected when the dataset is destroyed.
Which approach shall I use? I guess I'd want to prevent the independent
term set from ever being garbage collected. I can't use a light userdata
pointer because the access function must return a full usable Lua
object. I also shouldn't duplicate the term set because it's expensive
and the two copies could fall out of sync, which is undesirable.
Thanks for any suggestions.
s