lua學習之異常處理
https://www.cnblogs.com/NewMan13/p/7860404.html
轉載:http://blog.csdn.net/yuanfengyun/article/details/53454488
1、基本概念
lua本質上利用C函式來操作LUA虛擬機器。LUA虛擬機器對於C來說只是在堆上的記憶體物件。
lua有自己的執行物件(協程),每個協程有自己的呼叫棧。
比如下面的函式:
function add(x, y)
return x + y
end
如果x或y不能進行加法操作,在呼叫中就會產生異常。產生了異常,虛擬機器需要對異常進行處理,最簡單粗暴的處理是直接退出程式。
但這樣肯定是不符合一門現在語言對異常處理能力的要求。lua虛擬機器的做法是把異常交給使用者之前定義的異常處理函式來進行處理。比如是打印出異常資訊,打印出呼叫棧。使用者的異常處理函式處理完以後,虛擬機器還需要恢復到正常的執行流程中。但是恢復到哪一層的呼叫棧,不同時候是不一樣的。虛擬機器會從上一層函式開始,直到能找到一個異常恢復點。找到異常恢復點以後,虛擬機器將程式狀態恢復正常,並從恢復點再次開始執行。
2、普通呼叫
function main()
local c = add(1, nil)
print(c)
end
假如上述main函式在呼叫時呼叫棧為
main()
add()
在add函式中出現異常,由於add的上一層沒有異常恢復點,異常會繼續向上丟擲。後面的print語句不會被執行。
3、使用安全呼叫
function main()
local c
local success, c = pcall(add, x, y)
if success then
print("c is ", c)
else
print("exception accur")
end
end
上面修改過的main使用了安全呼叫的方式,呼叫add之前,生成了一個恢復點,當add中出現異常,向上丟擲時,遇到了恢復點,程式恢復到了正常執行狀態。當呼叫中沒有異常發生,pcall會返回true和add的返回值;當發生異常時,pcall會返回false。
4、使用函式安全呼叫並使用自定義的異常處理函式
在lua.c中異常發生時,預設的異常處理函式會呼叫luaL_traceback。它會先打印出異常資訊,然後再打印出呼叫棧。在lua程式碼中,如果需要指定自己的異常處理函式,可以使用xpcall,以第二個引數中傳入自己的異常處理函式。
exp = function (msg) print(msg) end
function main()
local c
local success, c = xpcall(add, exp, x, y)
if success then
print("c is ", c)
else
print("exception accur")
end
end
在傳入自己的異常處理函式之後,在發生異常時,虛擬機器會呼叫該函式,而不是上層的處理函式。
5、主動丟擲異常
在lua程式碼中可以簡單通過error函式丟擲異常。assert函式相當於對error函式進行了包裝,通過條件判斷是否需要丟擲異常。
function add(x, y)
if type(x) ~= "number" then
error("x is not a number")
end
if type(y) ~= "number" then
error("y is not a number")
end
end
分類: lua