lua-users home
lua-l archive

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


Hi all,

WARNING: Long winded email coming up.

My system is Windows XP SP2 with MinGW 5.1.2/gcc v3.4.5 and Lua 5.1.2. I am not sure if this is a Lua issue or a lack of understanding on my part, so please bare with this. Thanks.

I am getting a SIGSEGV fault and I can't explain it. When I call a cfunction with a incorrect parameter and I use luaL_checkxxx() functions on the variable I am getting a SIGSEGV error. If you look at the lLog() function in the example below you can see my comment about making the variable static. Why is this needed? What principle am I missing? I feel kind of silly asking a C++ish question, but I think I am actually having a problem with the interaction between Lua and C++. The issue shows when the exception is thrown from the throw_errors() function, when the stack is unwinding.

I worked up an example. Sorry it is a bit big but it shows the problem involves exceptions:
(I used the binary static library from LuaBinary on LuaForge [ http://luaforge.net/frs/download.php/2239/lua5_1_2_Win32_mingw3_lib.zip])

<code - main.cpp>
#include <iostream>
#include <string>
#include <exception>

#include "lua.hpp "

namespace lua
{
    /** A generic lua exception.
     */
    class exception : public std::exception
    {
    public:
        /// Constructor.
        exception() : std::exception() { }

        /// Constructor.
        explicit exception( const char* desc ) : std::exception(), description( desc ) { }

        virtual ~exception() throw() { }

        /** Get a description of the error.
         * @returns a C-string describing the error
         */
        virtual const char* what() const throw()
        {
            return description.c_str();
        }

    private:
        std::string description;
    };

    int throw_error( lua_State* luaState, int code )
    {
        const char* error;

        // below, we package lua errors into exceptions
        if ( code != 0 )
        {
            error = lua_tostring( luaState, -1 );
            lua_pop( luaState, 1 );

            throw exception( error );
        }

        return code;
    }
}

static int lLog( lua_State* luaState )
{
    //static
    std::string val; // <- by not declaring this static I can't unwind the stack.
    size_t l;

    // Get the function argument and also check it.
    const char* c = luaL_checklstring( luaState, 1, &l );

    // Assign the string to a standard string.
    val.assign( c, l );

    // Call the real function.
    std::cout << "[DEBUG] " << val << std::endl;

    return 0; // number of return values
}

int main( int argc, char* argv[] )
{
    // Check for commandline arguments.
    if ( argc < 2 )
    {
        std::cerr << "Requires a script file passed to the executable" << std::endl;
        return 1;
    }

    try
    {

        // Create a new Lua state.
        lua_State* L = luaL_newstate();
        if ( L != NULL )
        {
            // opens all the Lua libraries.
            luaL_openlibs( L );
            // register test function.
            lua_register( L, "log", lLog );
            // Load the script.
            luaL_loadfile( L, argv[1] );
            // Run the script.
            lua::throw_error( L, lua_pcall( L, 0, 0, 0 ) );
            // Close the Lua state.
            lua_close( L );
        }
        else
            return 1;
    }
    catch( lua::exception& ex )
    {
        std::cerr << ex.what() << std::endl;
    }

    std::cout << "Finshed test..." << std::endl;
    return 0;
}
<endcode - main.cpp>

<code - test.lua>
log( "Script entered" )

print( "This is a test to see if the lua_checklstring() function fails" )
print( "and recovery is possible." )
-- Call 'log()' with no parameter to make sure check fails.
log( )

log( "Script exited" )
<endcode - test.lua>
--
Regards,
Ryan
RJP Computing