Lua 錯誤處理


程式運行中錯誤處理是必要的,在我們進行檔案操作,資料轉移及web service 呼叫過程中都會出現不可預期的錯誤。如果不注重錯誤訊息的處理,就會照成資訊洩露,程式無法運作等情況。

任何程式語言中,都需要錯誤處理。錯誤類型有:

  • 語法錯誤

  • 運行錯誤


語法錯誤

語法錯誤通常是由於對程式的元件(如運算子、表達式)使用不當引起的。一個簡單的實例如下:

-- test.lua 文件
a == 2

以上程式碼執行結果為:

lua: test.lua:2: syntax error near '=='

如你所看到的,以上出現了語法錯誤,一個"=" 號跟兩個"="號是有差別的。一個 "=" 是賦值表達式兩個 "=" 是比較運算。

另外一個實例:

for a= 1,10
   print(a)
end

執行以上程式會出現以下錯誤:

lua: test2.lua:2: 'do' expected near 'print'

語法錯誤比程式執行錯誤更簡單,執行錯誤無法定位具體錯誤,而語法錯誤我們可以很快的解決,如以上實例我們只要在for語句下添加do 即可:

for a= 1,10
do
   print(a)
end

運行錯誤

運行錯誤是程式可以正常執行,但是會輸出報錯訊息。如下實例由於參數輸入錯誤,程式執行時報錯:

function add(a,b)
   return a+b
end

add(10)

當我們編譯執行以下程式碼時,編譯是可以成功的,但在執行的時候會產生如下錯誤:

lua: test2.lua:2: attempt to perform arithmetic on local 'b' (a nil value)
stack traceback:
	test2.lua:2: in function 'add'
	test2.lua:5: in main chunk
	[C]: ?

以下報錯資訊是由於程式缺少b 參數所引起的。


錯誤處理

我們可以使用兩個函數:assert 和 error 來處理錯誤。實例如下:

local function add(a,b)
   assert(type(a) == "number", "a 不是一个数字")
   assert(type(b) == "number", "b 不是一个数字")
   return a+b
end
add(10)

執行以上程式會出現如下錯誤:

lua: test.lua:3: b 不是一个数字
stack traceback:
	[C]: in function 'assert'
	test.lua:3: in local 'add'
	test.lua:6: in main chunk
	[C]: in ?

實例中assert首先檢查第一個參數,若沒問題,assert不做任何事情;否則,assert以第二個參數作為錯誤訊息拋出。

error函數

語法格式:

error (message [, level])

功能:終止正在執行的函數,並傳回message的內容為錯誤訊息(error函數永遠不會回傳)

通常情況下,error會附加一些錯誤位置的資訊到message頭部。

Level參數指示獲得錯誤的位置:

  • Level=1[預設]:為呼叫error位置(檔案+行號)

  • Level=2:指出哪個呼叫error的函數的函數

  • Level=0:不加入錯誤位置資訊


pcall 和xpcall、debug

Lua中處理錯誤,可以使用函數pcall(protected call)來包裝需要執行的程式碼。

pcall接收一個函數和要傳遞個後者的參數,並執行,執行結果:有錯誤、無錯誤;傳回值true或或false, errorinfo。

語法格式如下

if pcall(function_name, ….) then
-- 没有错误
else
-- 一些错误
end

簡單實例:

> =pcall(function(i) print(i) end, 33)
33
true
   
> =pcall(function(i) print(i) error('error..') end, 33)
33
false        stdin:1: error..
<p這裡注意對回傳值的邏輯判斷:< p="">
> function f() return false,2 end
> if f() then print '1' else print '0' end
0

pcall以一種"保護模式"來呼叫第一個參數,因此pcall可以捕捉函數執行中的任何錯誤。

通常在錯誤發生時,希望落得更多的偵錯訊息,而不只是發生錯誤的位置。但pcall回傳時,它已經銷毀了呼叫桟的部分內容。

Lua提供了xpcall函數,xpcall接收第二個參數-一個錯誤處理函數,當錯誤發生時,Lua會在呼叫桟展看(unwind)前呼叫錯誤處理函數,於是就可以在這個函數中使用debug函式庫來取得關於錯誤的額外資訊了。

debug庫提供了兩個通用的錯誤處理函數:


  • #debug.debug:提供一個Lua提示符,讓使用者來價差錯誤的原因

  • debug.traceback:根據呼叫桟來建構一個擴充的錯誤訊息

>=xpcall(function(i) print(i) error( 'error..') end, function() print(debug.traceback()) end, 33) 33 stack traceback: stdin:1: in function