lua-users home
lua-l archive

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




On Wed, Aug 31, 2011 at 11:49 AM, Sean Conner <sean@conman.org> wrote:
It was thus said that the Great Sean Conner once stated:
> It was thus said that the Great oliver once stated:
> >
> > Programmers make mistakes when using library functions/methods, utility or
> > not. For optimal productivity, a library should assert its preconditions, at
> > least in debug build. It is an error *not* to check. Since some of us have
> > to (for variety of reasons) use pre-built release-mode Lua DLL, where
> > preconditions are therefore not asserted, and given that the
> > "is-acceptable-index" formula is not trivial, and that this precondition is
> > so prevalent in Lua lib, there should at least be a Lua lib function that
> > allows to validate stack indices.
>
>   I think you gave the solution in another email---lua_gettop()!  Here:
>
> int mylua_isacceptable(lua_State *L,int idx)
> {
>   return abs(idx) <= lua_gettop(L);
> }
>
>   -spc (Or am I missing something?)

 Okay, in re-reading the thread, I see I am missing something.  Oliver
wants to check that an index is acceptable and thus, feels the need to know
the physical size of the stack at that instance, instead of the current top
of the stack.

 But in thinking about it, the code above is what you really want.  If you
(as programmer) are trying to access stack entries you know nothing about
(outside of lua_gettop()) then you are doing something wrong, regardless of
the size of the stack (but I am willing to conceed that this issue has never
bitten me, probably because of all my years of programming in assembly,
where one is working with a raw, system controlled, stack).

 -spc

[sorry for long reply]
I find it puzzling that the Lua ref manual refers to a precondition, index acceptability, that cannot, apparently, be tested. In Lua 5.1, stack element index values have the following characteristics (note distinction between "(" and "[" for open/closed sets): 
  1. if top == 0, all index values are not-an-index (not-acceptable); OTHERWISE
  2. [MIN_INT .. -top):      not-an-index (not acceptable)
  3. [-top .. -1]:           acceptable and valid
  4. [0]:                    not-an-index (not acceptable)
  5. [1 .. top]:             acceptable and valid
  6. (top .. stacksize]:     acceptable but non-valid
  7. (stacksize .. MAX_INT]: not-an-index (not acceptable)
The Lua C API allows you to test #1 to #5, but *not* #6 or #7. YET the Lua ref manual mentions in a lot of places that A happens if #3 or #5, and B happens if #6. 

The problem is that a lot of users (judging by posts) think that #6 is the same as "not (#3 or #5)", which makes them expect well-defined behavior for all index values. Until something eventually goes wrong in their app and after a lot of digging, they realize their mistake. The fix is then to call lua_something() only for #3, 5 or 6, else do something sensible yourself. But oops, #6 can't be tested. So call lua_something only if #3 or #5. Ie, never call lua_something() unless it satisfies #3 or 5. The extra words about "but B happens if non-valid (#6)" are not only irrelevant, they are too easily confused with "but B happens if index value not (#3 or 5) condition" which can easily lead to undefined behavior. 

Summary: it could save growing pains if manual dropped the "acceptable" and "non-valid" stuff and used format like 

"function so-and-so does such-and-such if index is "valid", *otherwise* behavior is underfined". 

AND define "valid" somewhere as "abs(index) in [1..gettop()]" (which covers condition #1 as well). Better, additionally provide a lua_isindexvalid() function that does this so everyone has one place to go to for asserting that operations will produce well-defined behavior. 

Oliver