2011-02-06 16 views
1

私はLuaを埋め込み、Cの非常に単純なイベントモジュールであると書いています。問題はアプリケーションを終了しようとするとセグメント違反です。 GDBは言う:Lua 5.1アプリケーションを終了するときのluaF_newprotoのセグメント化エラー

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) 

私はどちらかの次のいずれかを実行した場合、私は「ドンsegフォルトを取得する:

  1. _events_subscribe残念ながら

add_callbackへの呼び出しを削除main

  • luaL_openlibsへの呼び出しを削除し、私はそれを超えた何かを把握することができていません。私はevent.subscribe直後に別の関数を呼び出す場合はまた、アプリケーションがハングし、GDBレポート:

    Program received signal SIGSEGV, Segmentation fault. 
    0x002c00a8 in luaS_newlstr() from C:\Windows\SysWOW64\lua5.1.dll 
    

    任意のアイデア?

  • 答えて

    1

    私はそれが何かばかげていることを知っていました。 _events_subscribeluaL_refが間違っていました。それは:

    Callback* callback = add_callback(event, luaL_ref(L, LUA_REGISTRYINDEX)); 
    
    関連する問題