Garbage collection of userdata inside userdata

"'Stefano Cossu' via lua-l" <[email protected]> Tue, 14 Jul 2026 17:27:17 -0400
Newsgroups gmane.comp.lang.lua.general
Message-ID <[email protected]>
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

-- 
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/lua-l/54ee6152-3671-41cc-b6b6-d56b99101bdf%40cossu.cc.