退出应用程序时 luaF_newproto 处的 Lua 5.1 分段错误
我嵌入了 Lua 并用 C 编写了一个非常简单的事件模块。问题是,当我尝试退出应用程序时,我收到了分段错误。 GDB 说:
Program received signal SIGSEGV, Segmentation fault.
0x003a72c3 in luaF_newproto () from C:\Windows\SysWOW64\lua5.1.dll
模块:
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include "ice.h"
typedef struct Callback_t {
int ref;
struct Callback_t* next;
} Callback;
typedef struct Event_t {
char* name;
Callback* chead;
struct Event_t* next;
} Event;
static Event* ehead = NULL;
static Event* find_event(char* name) {
Event* current = ehead;
while (current) {
if (strcmp(current->name, name) == 0)
return current;
current = current->next;
}
return NULL;
}
static Event* add_event(char* name) {
Event* event = find_event(name);
if (event == NULL) {
event = (Event*)malloc(sizeof(Event));
if (event == NULL)
return NULL;
event->name = name;
event->chead = NULL;
event->next = ehead;
ehead = event;
}
return event;
}
static Callback* find_callback(Event* event, int ref) {
Callback* current = event->chead;
while (current) {
if (current->ref == ref)
return current;
current = current->next;
}
return NULL;
}
static Callback* add_callback(Event* event, int ref) {
Callback* callback = find_callback(event, ref);
if (callback == NULL) {
callback = (Callback*)malloc(sizeof(Callback));
if (callback == NULL)
return NULL;
callback->ref = ref;
callback->next = event->chead;
event->chead = callback;
}
return callback;
}
static int _events_subscribe(lua_State* L) {
const char* name = luaL_checkstring(L, 1);
if (!lua_isfunction(L, 2))
luaL_typerror(L, 2, lua_typename(L, LUA_TFUNCTION));
Event* event = add_event((char*)name);
if (event == NULL)
luaL_error(L, "Failed to allocate memory for event.");
Callback* callback = add_callback(event, luaL_ref(L, 2));
if (callback == NULL)
luaL_error(L, "Failed to allocate memory for event callback.");
return 0;
}
static int _events_unsubscribe(lua_State* L) {
// Not implemented yet
return 0;
}
static const luaL_reg _events_methods[] = {
{ "subscribe", _events_subscribe },
{ "unsubscribe", _events_unsubscribe },
{ NULL, NULL }
};
int luaopen_events(lua_State* L) {
luaL_openlib(L, "events", _events_methods, 0);
lua_pop(L, 1);
return 0;
}
void lua_closeevents(lua_State* L) {
Event* event = ehead;
while (event) {
Callback* callback = event->chead;
while (callback) {
Callback* cnext = callback->next;
free(callback);
callback = cnext;
}
Event* enext = event->next;
free(event);
event = enext;
}
}
主要:
#include <stdlib.h>
#include <windows.h>
#include <SDL/SDL.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "ice.h"
lua_State* Lua;
SDL_Surface* screen;
void cleanup() {
SDL_Quit();
lua_closeevents(Lua);
lua_close(Lua);
}
int main(int argc, char** argv) {
Lua = lua_open();
if (Lua == NULL)
FATAL_ERROR("Failed to initialize Lua scripting engine.", NULL);
luaL_openlibs(Lua);
luaopen_events(Lua);
if (SDL_Init(SDL_INIT_VIDEO) == -1)
FATAL_ERROR("Failed to initialize SDL subsystems.", NULL);
atexit(cleanup);
screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
if (screen == NULL)
FATAL_ERROR("Failed to set video mode.", NULL);
if (argc > 1) {
if (luaL_loadfile(Lua, argv[1]) != 0 || lua_pcall(Lua, 0, LUA_MULTRET, 0) != 0) {
const char* msg = lua_tostring(Lua, -1);
if (msg == NULL) msg = "No error message available.";
FATAL_ERROR("%s", msg);
}
} else {
FATAL_ERROR("No startup script specified.", NULL);
}
SDL_Event event;
do {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_VIDEORESIZE:
DEBUG_WRITE("Resize", NULL);
screen = SDL_SetVideoMode(event.resize.w, event.resize.h,
screen->format->BitsPerPixel, screen->flags);
break;
case SDL_USEREVENT:
switch (event.user.code) {
case SDL_USER_VIDEOFLAGS:
screen = SDL_SetVideoMode(screen->w, screen->h,
screen->format->BitsPerPixel,
*(int*)event.user.data1);
break;
}
break;
default:
break;
}
}
} while (event.type != SDL_QUIT);
return EXIT_SUCCESS;
}
测试脚本:
function OnKeyDown()
return
end
events.subscribe("OnKeyDown", OnKeyDown)
如果我执行以下任一操作,我不会收到段错误:
- 删除
main
中对luaL_openlibs
的调用 - 删除 。
不幸的是,我无法弄清楚除此之外的任何事情 此外,如果我在 event.subscribe
之后立即调用另一个函数,应用程序将挂起并且 GDB 报告:
Program received signal SIGSEGV, Segmentation fault.
0x002c00a8 in luaS_newlstr () from C:\Windows\SysWOW64\lua5.1.dll
Any ideas?
I've embedded Lua and written what's supposed to be a very simple event module in C. The problem is, when I try to exit my application, I receive a segmentation fault. GDB says:
Program received signal SIGSEGV, Segmentation fault.
0x003a72c3 in luaF_newproto () from C:\Windows\SysWOW64\lua5.1.dll
Module:
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include "ice.h"
typedef struct Callback_t {
int ref;
struct Callback_t* next;
} Callback;
typedef struct Event_t {
char* name;
Callback* chead;
struct Event_t* next;
} Event;
static Event* ehead = NULL;
static Event* find_event(char* name) {
Event* current = ehead;
while (current) {
if (strcmp(current->name, name) == 0)
return current;
current = current->next;
}
return NULL;
}
static Event* add_event(char* name) {
Event* event = find_event(name);
if (event == NULL) {
event = (Event*)malloc(sizeof(Event));
if (event == NULL)
return NULL;
event->name = name;
event->chead = NULL;
event->next = ehead;
ehead = event;
}
return event;
}
static Callback* find_callback(Event* event, int ref) {
Callback* current = event->chead;
while (current) {
if (current->ref == ref)
return current;
current = current->next;
}
return NULL;
}
static Callback* add_callback(Event* event, int ref) {
Callback* callback = find_callback(event, ref);
if (callback == NULL) {
callback = (Callback*)malloc(sizeof(Callback));
if (callback == NULL)
return NULL;
callback->ref = ref;
callback->next = event->chead;
event->chead = callback;
}
return callback;
}
static int _events_subscribe(lua_State* L) {
const char* name = luaL_checkstring(L, 1);
if (!lua_isfunction(L, 2))
luaL_typerror(L, 2, lua_typename(L, LUA_TFUNCTION));
Event* event = add_event((char*)name);
if (event == NULL)
luaL_error(L, "Failed to allocate memory for event.");
Callback* callback = add_callback(event, luaL_ref(L, 2));
if (callback == NULL)
luaL_error(L, "Failed to allocate memory for event callback.");
return 0;
}
static int _events_unsubscribe(lua_State* L) {
// Not implemented yet
return 0;
}
static const luaL_reg _events_methods[] = {
{ "subscribe", _events_subscribe },
{ "unsubscribe", _events_unsubscribe },
{ NULL, NULL }
};
int luaopen_events(lua_State* L) {
luaL_openlib(L, "events", _events_methods, 0);
lua_pop(L, 1);
return 0;
}
void lua_closeevents(lua_State* L) {
Event* event = ehead;
while (event) {
Callback* callback = event->chead;
while (callback) {
Callback* cnext = callback->next;
free(callback);
callback = cnext;
}
Event* enext = event->next;
free(event);
event = enext;
}
}
Main:
#include <stdlib.h>
#include <windows.h>
#include <SDL/SDL.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "ice.h"
lua_State* Lua;
SDL_Surface* screen;
void cleanup() {
SDL_Quit();
lua_closeevents(Lua);
lua_close(Lua);
}
int main(int argc, char** argv) {
Lua = lua_open();
if (Lua == NULL)
FATAL_ERROR("Failed to initialize Lua scripting engine.", NULL);
luaL_openlibs(Lua);
luaopen_events(Lua);
if (SDL_Init(SDL_INIT_VIDEO) == -1)
FATAL_ERROR("Failed to initialize SDL subsystems.", NULL);
atexit(cleanup);
screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
if (screen == NULL)
FATAL_ERROR("Failed to set video mode.", NULL);
if (argc > 1) {
if (luaL_loadfile(Lua, argv[1]) != 0 || lua_pcall(Lua, 0, LUA_MULTRET, 0) != 0) {
const char* msg = lua_tostring(Lua, -1);
if (msg == NULL) msg = "No error message available.";
FATAL_ERROR("%s", msg);
}
} else {
FATAL_ERROR("No startup script specified.", NULL);
}
SDL_Event event;
do {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_VIDEORESIZE:
DEBUG_WRITE("Resize", NULL);
screen = SDL_SetVideoMode(event.resize.w, event.resize.h,
screen->format->BitsPerPixel, screen->flags);
break;
case SDL_USEREVENT:
switch (event.user.code) {
case SDL_USER_VIDEOFLAGS:
screen = SDL_SetVideoMode(screen->w, screen->h,
screen->format->BitsPerPixel,
*(int*)event.user.data1);
break;
}
break;
default:
break;
}
}
} while (event.type != SDL_QUIT);
return EXIT_SUCCESS;
}
Test script:
function OnKeyDown()
return
end
events.subscribe("OnKeyDown", OnKeyDown)
If I do either one of the following, I don't get the seg fault:
- Remove the call to
luaL_openlibs
inmain
- Remove the call to
add_callback
in_events_subscribe
Unfortunately, I haven't been able to figure out anything beyond that. In addition, if I call another function immediately after event.subscribe
, the application hangs and GDB reports:
Program received signal SIGSEGV, Segmentation fault.
0x002c00a8 in luaS_newlstr () from C:\Windows\SysWOW64\lua5.1.dll
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我知道这会是一件愚蠢的事情。我在
_events_subscribe
中错误地使用了luaL_ref
。应该是:I knew it was going to be something silly. I was using
luaL_ref
incorrectly in_events_subscribe
. It should be: