lua-users home
lua-l archive

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


After recent questions about is it "safe" to use Lua, and a couple of application crashes of my own, I am starting to wonder if I have been doing it 100% correctly.

There is an example in the PIL book (Listing 24.1) along these lines (I have slightly simplified it):

---------------
#include "lua.h"
#include "lauxlib.h"

char buff [] = "print 'hi'";

int main (void)
  {
  lua_State * L = luaL_newstate ();
  luaL_openlibs (L);
  int error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
                lua_pcall(L, 0, 0, 0);
  return 0;
  } // end of main
---------------

Isn't there a problem here? What if luaL_loadbuffer fails? For example, out of memory? We can simulate a failure with this example program, which in essence does what caused my application to crash recently:

---------------
#include "lua.h"
#include "lauxlib.h"
#include <stdio.h>

int main (void)
  {
  lua_State * L = luaL_newstate ();
  lua_pushnil (L);
  luaL_checkstring (L, -1);   --> error, string not on stack
  printf ("Hello, world\n");
  return 0;
  } // end of main
---------------

If I run this at the command-line I get this message:

PANIC: unprotected error in call to Lua API (bad argument #-1 (string expected, got nil))


If I run the equivalent code in my (Windows GUI) application it crashes the application with some sort of error in Lua5.1.dll.


Would the correct method be to always wrap any attempts to use the Lua functions into a protected environment? - like in this example:

---------------
#include "lua.h"
#include "lauxlib.h"
#include <stdio.h>

// do things here that might fail
int stub(lua_State *L)
  {
  lua_pushnil (L);
  luaL_checkstring (L, -1);
  }

int main (void)
  {
  lua_State * L = luaL_newstate ();
  lua_pushcfunction (L, stub);
  int error = lua_pcall (L, 0, 0, 0);
  printf ("stub returned %i\n", error);
  printf ("Hello, world\n");
  return 0;
  } // end of main
---------------


I am familiar with doing lua_pcall to run the code that I ultimately want to run in a safe way, but I usually did something like this:

lua_getglobal (L, "somefunction");  --> get some function
lua_pushstring (L, "blah blah");  --> push arguments to function
lua_pcall (L, 1, 1, 0);  --> call the function
const char * p = lua_checkstring (L, -1);  --> oops! this might fail


So really, the whole sequence above should be protected itself by another level of lua_pcall, like I described. Am I right?

- Nick