lua-users home
lua-l archive

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




Roberto Ierusalimschy <roberto@inf.puc-rio.br> 于2020年9月2日周三 下午11:52写道:

What do you mean by "safe"? What is exactly your concerns?

I mean, if the C stack unwind before calling __close when raising an
error, the pointer is unsafe. because it's on the C stack.

You are thinking in the wrong abstraction level. When Lua calls __close,
the table containing the pointer is given as a parameter. So, it is
in slot #1, as valid as it was before the call. Lua never collects
an object and uses it afterwards.


int
foobar(lua_State *L) {
  struct mystruct foo;
  lua_settop(L, 0);

  lua_newtable(L);   // index 1 <—— CLOSED
  lua_pushlightuserdata(L, &foo);
  lua_setfield(L, 1, "_ptr"); // CLOSED._ptr = &foo

  lua_newtable(L);
  lua_pushcfunction(L, close_foo);
  lua_setfield(L, -2, "__close");
  lua_setmetatable(L, 1);

  lua_toclose(L, 1);   // index 1 is a to-be-closed "variable"

  ...

  return 0;
}

Lua calls CLOSED.__close() after foobar() returns, but CLOSED._ptr is the address on the C stackframe of the foobar(). It fells like:

struct mystruct *
foobar() {
    struct mystruct foo;
    mystruct_init(&foo);
    return &foo;
}

struct mystruct *ptr = foobar();
mystruct_exit(ptr);

It’s incorrect because the object foo is on the stack and we can’t use &foo after foobar() returns.

I think the point is that the lifespan of lua function foobar’s stackframe (slot #1) is longer than C stackframe of foobar.