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?
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.
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.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With