Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua: Can this cause a segfault

Tags:

c++

lua

I'm developing a program which uses Lua for scripting, and sometimes it would crash. With GDB I think I found the problem, but I don't know if it solved it, as the segfault would only occur sporadically. So, the old code was this:

void Call(std::string func){
    lua_getglobal(L, func.c_str()); //This is the line GDB mentioned in a backtrace
    if( lua_isfunction(L,lua_gettop(L)) ) {
        int err = lua_pcall(L, 0, 0,0 );
        if(err != 0){
            std::cout << "Lua error: " << luaL_checkstring(L, -1) << std::endl;
        }
    }
}

The thing is, that this function would be called a few times per second, but the function it needs to call isn't always defined, so I thought that the stack would overflow. I added the following line:

lua_pop(L,lua_gettop(L));

And the segfault hasn't occurred anymore. Could this have been the problem?

like image 308
Dirk Avatar asked Sep 03 '14 14:09

Dirk


People also ask

How do you find the cause of Segfault?

Use debuggers to diagnose segfaults Start your debugger with the command gdb core , and then use the backtrace command to see where the program was when it crashed. This simple trick will allow you to focus on that part of the code.

What causes a SIGSEGV?

A SIGSEGV signal or segmentation error occurs when a process attempts to use a memory address that was not assigned to it by the MMU.

Can out of memory cause segmentation fault?

Rarely, a segmentation fault can be caused by a hardware error, but for our purposes we will be taking a look at software-based memory access errors. Although, segmentation faults are the result of invalid memory access, incorrect access to memory will not always result in a segmentation fault.


1 Answers

Using lua_gettop(L) as the argument for lua_pop will clear the entire Lua API stack (it is equivalent to lua_settop(0)), which is probably not what you want. But indeed your problem is that lua_getglobal always pushes something; if no global with the given name exists, it pushes nil, just like the equivalent Lua expression would do. However, lua_pcall pops the function and all arguments (if any; in your case you specified zero), so you won't get a problem if the function exists. What you should do is adding lua_pop(L, 1) to an else clause of the outer if. This way, your function will always be balanced (i.e. leave the stack as it was).

You can see these things in the Lua manual: For every function, it is spelled out in the description and also indicated in grey, in brackets beside the functions prototype. For example, lua_getglobal has [-0, +1, e] meaning that it will pop no elements and (always) push one element (and the e meanst that it may cause errors).

like image 69
Oberon Avatar answered Oct 01 '22 04:10

Oberon