2

Cortex-M3 ターゲット (STM32F107) 用の MDK-ARM Pro 4.71、Keil を使用しています。

Lua インタープリターと、チップのタイマーを接続する Lua「タイマー」モジュールをコンパイルしました。タイマーが経過したときにlua関数を呼び出したいです。

使用例は次のとおりです。

t = timer.open()
t.event = function() print("Bing !") end
t:start()

ここまでは、すべて正常に動作します :-) ! 「ビンビン!」が見えます。タイマーが経過するたびにメッセージが出力されます。

クロージャーを使用する場合:

t = timer.open()
i = 0
t.event = function() i = i + 1; print(i); end
t:start()

一定量のタイマーの更新後、GC でメモリ アクセスがうまくいきません。これはメモリがほとんどない組み込みコンテキストであるため、リークがあるとメモリがすぐに不足する可能性があります。

これが "t.event" セッターです (ELIB_TIMER は私のタイマーを表す C 構造体です):

static int ElibTimerSetEvent(lua_State* L)
{
   ELIB_TIMER* pTimer_X = ElibCheckTimer(L, 1, TRUE);

   if (pTimer_X->LuaFuncKey_i != LUA_REFNIL)
   {
      luaL_unref(L, LUA_REGISTRYINDEX, pTimer_X->LuaFuncKey_i);
      pTimer_X->LuaFuncKey_i = LUA_REFNIL;
   }

   if (!lua_isnil(L, 2))
   {
      pTimer_X->LuaFuncKey_i = luaL_ref(L, LUA_REGISTRYINDEX);
   }

   return 0;
}

そして、ネイティブ コールバックの実装は次のとおりです。

static void ElibTimerEventHandler(SYSEVT_HANDLE Event_H)
{
   ELIB_TIMER* pTimer_X = (ELIB_TIMER*)SWLIB_SYSEVT_GetSideData(Event_H);
   lua_State* L = pTimer_X->L;
   int i = lua_gettop(L);
   if (pTimer_X->LuaFuncKey_i != LUA_REFNIL)
   {
      lua_rawgeti(L, LUA_REGISTRYINDEX, pTimer_X->LuaFuncKey_i);
      lua_call(L, 0, 0);
      lua_settop(L, i);
   }
}

これは外部で同期されるため、同期の問題ではありません。

私は何か間違っていますか?

編集

これがコールスタックです (lua_call の代わりに lua_pcall を使用していますが、同じです)。最初の行は、ハード フォールト ハンドラです。

Lua コール スタック

4

2 に答える 2

2

問題が見つかりました!スタック (Lua ではなくネイティブ スタック) のスペースが不足しました :p。この特定のスクリプトが特に長いコール スタックを引き起こしていると思います。ネイティブ スタックに割り当てられたメモリを増やした後、問題はなくなりました。逆に小さくすると、インタプリタの初期化すらできなくなります。

ここで助けようとした人々に感謝します。

于 2013-08-20T06:59:15.140 に答える
1

C コードにバグが見つかりました。あなたはluaスタックを壊しましたstatic int ElibTimerSetEvent(lua_State* L)

luaL_refLua スタックの一番上に値をポップします: http://www.lua.org/manual/5.2/manual.html#luaL_ref

したがって、次の呼び出しの前に、参照する値をコピーする必要がありますluaL_ref

lua_pushvalue(L, 2); // push the callback to stack top, and then it will be consumed by luaL_ref()

これを修正して、もう一度お試しください。

于 2013-08-20T03:25:22.883 に答える