[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Lua crashing on C function exit
- From: Derakon <derakon@...>
- Date: Sun, 24 Apr 2005 10:07:42 -0700
I sent this email earlier, but it appears to have not gone through. In
any event, I didn't receive it. Apologies if I'm double-messaging the
list.
I have an...interesting bug in my program: when I finish calling a C
function from a Lua script, I get this:
Program received signal EXC_BAD_ACCESS, Could not access memory.
0x00024698 in lua_gettop () at /usr/include/gcc/darwin/3.3/c++/iostream:76
76 // For construction of filebuffers for cout, cin, cerr, clog et. al.
The odd thing is that I've successfully called this C function before,
many times in fact. I've looked to see what could be different about
the specific (repeatable) case that I'm dealing with, and have turned
up nothing. So I'm turning it over to you guys, along with all the
context I can muster. Any assistance would be greatly appreciated.
First off, here's the Lua initialization. This is done on a per-sprite
basis (I'm writing a scripted game engine):
---
//Initialize a bunch of Lua stuff.
void Sprite::setupLua(void)
{
L = lua_open();
luaopen_base(L);
luaopen_table(L);
luaopen_io(L);
luaopen_string(L);
luaopen_math(L);
luaopen_debug(L);
lua_pushcfunction(L, Sprite::spawnSprite);
lua_setglobal(L, "spawnSprite");
lua_pushcfunction(L, Sprite::getSprite);
lua_setglobal(L, "getSprite");
int error = luaL_loadfile(L, scriptFile.c_str()) ||
(lua_pcall(L, 0, 0, 0));
if (error)
{
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
exit(111);
}
lua_getglobal(L, "init");
pushState();
callLua(1, 1, "init");
popState("init");
}
---
Now, here's pushState and popState. They're designed to clean up some
of the mess caused by dealing with the Lua stack. In lieu of actually
keeping track of the stack's state, I just empty it out in popState;
this should actually work just fine as pushState occurs before every
Lua "transaction" and popState occurs after; no residual information
is required. Unless I'm missing something...? Regardless, I only
started doing this when I discovered that I had upwards of 200 objects
on the stack; this was in the process of tracking down the bug I'm
currently working on.
---
//Push the current sprite state onto the Lua stack, as a table.
void Sprite::pushState(void)
{
lua_newtable(L);
setfield(L, "dead", 0);
setfield(L, "vx", vel.x);
setfield(L, "vy", vel.y);
setfield(L, "x", boundingBox.getCenter().x);
setfield(L, "y", boundingBox.getCenter().y);
setfield(L, "anim", currentAnimation);
setfield(L, "advanceFrames", 0);
}
//Pop the current sprite state off of the Lua stack.
void Sprite::popState(const char* fun)
{
if (!lua_istable(L, -1))
{
cerr << "Error: script " << scriptFile << ", function " << fun <<
" did not return a valid sprite state\n";
exit(169);
}
//Short-circuit: if the sprite is dying, then we don't care about the rest.
int dead = (int) getfield(L, "dead");
if (dead)
{
world->killSprite(this);
return;
}
vel.x = getfield(L, "vx");
vel.y = getfield(L, "vy");
//(x, y) is actually the location of the sprite's center, not its upper
//corner.
Coord newLoc;
newLoc.x = getfield(L, "x");
newLoc.y = getfield(L, "y");
boundingBox.moveCenterTo(newLoc);
currentAnimation = (int) getfield(L, "anim");
int anim = (int) getfield(L, "advanceFrames");
animations[currentAnimation]->advanceTime(anim);
//Clean off the stack
lua_settop(L, 0);
}
---
Here's the spawnSprite function. It's pretty simple; it just
translates the Lua stack into something that normal C++ functions can
understand, and then hands responsibility off to the World class.
---
//Tell the world to spawn a new sprite.
int Sprite::spawnSprite(lua_State* L)
{
int id = (int) luaL_checknumber(L, 1);
int layer = (int) luaL_checknumber(L, 2);
int uniqueId = (int) luaL_checknumber(L, 3);
double x = (double) luaL_checknumber(L, 4);
double y = (double) luaL_checknumber(L, 5);
world->spawnSprite(id, layer, uniqueId, x, y);
return 0;
}
---
Finally, here's the call to spawnSprite in the Lua script, as well as
another script's call to the same function that doesn't break the
program:
---
function update (state)
--Spawn a bullet
if (timer == 0) then
spawnSprite(4, 0, 0, state.x, state.y) --And here the program dies
timer = 50
end
--Don't go off the edges of the screen
if (state.x < 50 or state.x > 590) then
state.vx = -state.vx
end
timer = timer - 1
state.x = state.x + state.vx
state.y = state.y + state.vy
return state
end
function update (state)
--Periodically spawn shooters
if (timer == 100) then
spawnSprite(3, 0, 0, 590, 50) --Works just fine
timer = 0
end
timer = timer + 1
return state
end
---
Now, I've traced this program through in gdb. It works perfectly up to
through "return 0" point. Then I get that error I mentioned before.
According to `top`, I'm only using about 110MB of memory for the
entire program, so I shouldn't actually be out of memory. I'd love to
hear any ideas you might have. Hell, any constructive criticism about
my overall style is appreciated. I've a long ways to go before this
project is presentable to the general populace, and I'd love to be
speeded on my way.
-Chris Weisiger