local lua 多個 檢測Lua指令碼中的死迴圈

2021-10-13 10:24:42 字數 1399 閱讀 7687

論壇上有人問,所以把以前做的東西拿出來秀一下。

lua是一門小巧精緻的語言,特別適用於嵌入其它的程式為它們提供指令碼支援。不過指令碼通常是使用者編寫的,很有可能出現死迴圈,雖說這是使用者的問題,但卻會造成我們的宿主程式死掉。所以檢測使用者指令碼中的死迴圈並中止這段指令碼的執行就顯得非常重要了。

可是,乙個現實的問題是死迴圈並不好檢測,一些隱藏較深的死迴圈連人都很難找出來,更不用說讓機器去找了。所以實際採用的方案多是檢測指令碼的執行時間,如果超過一定的限度,就認為裡面有死迴圈,***的例子也是用的這種方法。

以下是幾個相關的全域性變數(我是喜歡把c++當c用的程式設計師,c++的忠實粉絲請忍耐一下:))的定義。

1 lua_state*g_lua=null;//lua指令碼引擎2 volatileunsigned g_begin=0;//指令碼開始執行的時間3 volatilelongg_counter=0;//指令碼執行計數, 用於判斷執行超時4 volatilelongg_check=0;//進行超時檢查時的執行計數

run_user_script用來執行使用者指令碼,它首先通過gettickcount把當前的時間記錄到g_begin中去。然後將g_counter加一,在執行完使用者指令碼後再將其加一,這樣就可以保證執行使用者指令碼時它是個奇數,而不執行時是偶數,檢測指令碼超時的**可以籍此來判斷當前是否在執行使用者指令碼。還要注意呼叫使用者指令碼要使用lua_pcall而不是lua_call,因為我們中止指令碼的執行會產生乙個lua中的「錯誤」,在c/c++中它是乙個異常,只有用lua_pcall才能保證這個錯誤被lua指令碼引擎正確處理。

1 intrun_user_script(intnargs,intnresults,interrfunc )2 

下面的check_script_timeout用來檢測指令碼超時,需要在另外乙個執行緒中週期性的呼叫,原因我想就不用解釋了吧。它首先檢查是否在執行使用者指令碼,或者是否已經讓當前執行的使用者指令碼中止過。然後看這段指令碼執行了多長時間,超過限度就把當前指令碼計數記錄到g_check中去,並通過lua_sethook設定乙個鉤子函式timeout_break,這個鉤子函式會在使用者指令碼執行時被呼叫。

1 voidcheck_script_timeout()2 20 }

最後就是那個鉤子函式了,它首先把鉤子去掉,因為這個鉤子只要執行一次就行了。由於設定鉤子和執行鉤子是在不同的執行緒中,並且鉤子從設定到執行需要一定的時間,所以它要通過對比g_check和g_counter來判斷是否還在執行判斷超時所執行的那段指令碼,不是就什麼也不做,是就通過lual_error產生乙個錯誤,並中止指令碼的執行,而這個錯誤最終會被run_user_script中的lua_pcall捕獲。

1 voidtimeout_break( lua_state*l, lua_debug*ar )2 

上面的檢測使用了兩個執行緒,其實在乙個執行緒中也可以做到,並且更簡單。但那樣會導致鉤子函式頻繁執行,影響效率,如果對效能沒什麼要求的話,也可以採用。

local lua 多個 Lua 變數

lua 變數 變數在使用前,需要在 中進行宣告,即建立該變數。編譯程式執行 之前編譯器需要知道如何給語句變數開闢儲存區,用於儲存變數的值。lua 變數有三種型別 全域性變數 區域性變數 表中的域。lua 中的變數全是全域性變數,那怕是語句塊或是函式裡,除非用 local 顯式宣告為區域性變數。區域性...

local lua 多個 lua的local問題

1.初識 使用local帶來錯誤。自己寫了乙個遞迴的函式,結果報錯 local flocal function n if n 1 then returnn else return n flocal n 1 end endprint result flocal 2 錯誤資訊 lua rk work d...

CocosStudio使用Lua檢測按鈕點選

1.按鈕或者核取方塊要在scene下。2.布林值取反,是not。mainscene.lua local mainscene class mainscene cc.load mvc viewbase 載入csb檔案 mainscene.resource filename mainscene.csb 獲...