lua_error and C++ destructors

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

lua_error and C++ destructors

Dan Marks
Hello lua land,

I have a question about using lua_error in C++.  We have been
using lua in C++ but not with constructors/destructors.  I have
noticed that there is a longjmp() in lua_error.  Presumably
(at least according to gcc and MSVC++) this will prevent any
of the objects in the stack frames from having their destructors
called on them.  This presents a problem, as I allocate objects
on the stack that take up heap space and therefore this will
result in a memory leak.

Is there any workaround for it, and perhaps maybe in C++ this
should be handled using the exception mechanism?  Perhaps the
lua_call should be encapsulated in a try {} catch block?  The
only strategy I have been able to devise so far is:

void function_from_lua()
{
  int parm = luaL_check_number(1);
  int iserror = 0;
  {
    object o(myconstructordata);
 
    if (do_the_work_fails()) {
       iserror = 1;
    } 
  }  /* end of block ensures destructor executes */
  if (iserror)
    lua_error("Something bad happened");
}

It is doable, but seems kind of clunky.  Perhaps something
better exists?

Thank you

Dan Marks
[hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: lua_error and C++ destructors

David Jeske-2
On Sun, Jun 21, 1998 at 12:14:25PM -0300, Dan Marks wrote:
> Is there any workaround for it, and perhaps maybe in C++ this
> should be handled using the exception mechanism?  Perhaps the
> lua_call should be encapsulated in a try {} catch block?  The
> only strategy I have been able to devise so far is:
> 
> void function_from_lua()
> {
>   int parm = luaL_check_number(1);
>   int iserror = 0;
>   {
>     object o(myconstructordata);
>  
>     if (do_the_work_fails()) {
>        iserror = 1;
>     } 
>   }  /* end of block ensures destructor executes */
>   if (iserror)
>     lua_error("Something bad happened");
> }
> 
> It is doable, but seems kind of clunky.  Perhaps something
> better exists?

Interesting. if I were you, I would just stop allocating objects on the
stack inside functions called from lua, and then you can explicitly
deallocate them before you call lua_error(). Or use a goto to work like a
finally block:

void function_from_lua()
{
  int param = luaL_check_number(1);
  {  
    object o(construction args)
    
    if (do_the_work_fails()) {
       goto error;
    }

    if (we_find_another_error) {
       goto error;
    }

    // continue doing useful work
   
  }

  return; // success
error:
  lua_error("Something bad happened");
}

However, I agree this stuff is pretty ugly. However, C++ is pretty ugly,
especially when you allocate objects on the stack. :)

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: lua_error and C++ destructors

Roberto Ierusalimschy
In reply to this post by Dan Marks
  I guess one aproach is to use a try {} catch block, as you mentioned. If you
really plan to use lots of exception handling in C++, then do everything with
exceptions, and only in the Lua "borders" you convert from one to the other.
So, you could use:

void dofile (char *filename) {
  if (lua_dofile(filename) != 0)
    raise exception;  // I don't remember the C++ syntax...
}

etc for dostring, lua_call, ...

  Any C++ function called from Lua should catch all exceptions, and then call
lua_error in the handler. In this way, everytime you come from Lua to C++
errors are turned into exceptions, and when going from C++ to Lua exceptions
become errors. In your particular example, you should not use a flag (iserror),
but an exception, since that is C++.

-- Roberto