Lua 錯(cuò)誤處理

2022-01-29 10:33 更新

程序運(yùn)行中錯(cuò)誤處理是必要的,在我們進(jìn)行文件操作,數(shù)據(jù)轉(zhuǎn)移及web service 調(diào)用過程中都會出現(xiàn)不可預(yù)期的錯(cuò)誤。如果不注重錯(cuò)誤信息的處理,就會造成信息泄露,程序無法運(yùn)行等情況。

任何程序語言中,都需要錯(cuò)誤處理。錯(cuò)誤類型有:

  • 語法錯(cuò)誤
  • 運(yùn)行錯(cuò)誤

語法錯(cuò)誤

語法錯(cuò)誤通常是由于對程序的組件(如運(yùn)算符、表達(dá)式)使用不當(dāng)引起的。一個(gè)簡單的實(shí)例如下:

-- test.lua 文件
a == 2

以上代碼執(zhí)行結(jié)果為:

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

正如你所看到的,以上出現(xiàn)了語法錯(cuò)誤,一個(gè) "=" 號跟兩個(gè) "=" 號是有區(qū)別的。一個(gè) "=" 是賦值表達(dá)式兩個(gè) "=" 是比較運(yùn)算。

另外一個(gè)實(shí)例:

for a= 1,10
   print(a)
end

執(zhí)行以上程序會出現(xiàn)如下錯(cuò)誤:

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

語法錯(cuò)誤比程序運(yùn)行錯(cuò)誤更簡單,運(yùn)行錯(cuò)誤無法定位具體錯(cuò)誤,而語法錯(cuò)誤我們可以很快的解決,如以上實(shí)例我們只要在for語句下添加 do 即可:

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

運(yùn)行錯(cuò)誤

運(yùn)行錯(cuò)誤是程序可以正常執(zhí)行,但是會輸出報(bào)錯(cuò)信息。如下實(shí)例由于參數(shù)輸入錯(cuò)誤,程序執(zhí)行時(shí)報(bào)錯(cuò):

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

add(10)

當(dāng)我們編譯運(yùn)行以下代碼時(shí),編譯是可以成功的,但在運(yùn)行的時(shí)候會產(chǎn)生如下錯(cuò)誤:

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ào)錯(cuò)信息是由于程序缺少 b 參數(shù)引起的。


錯(cuò)誤處理

我們可以使用兩個(gè)函數(shù):assert 和 error 來處理錯(cuò)誤。實(shí)例如下:

local function add(a,b)
   assert(type(a) == "number", "a 不是一個(gè)數(shù)字")
   assert(type(b) == "number", "b 不是一個(gè)數(shù)字")
   return a+b
end
add(10)

執(zhí)行以上程序會出現(xiàn)如下錯(cuò)誤:

lua: test.lua:3: b 不是一個(gè)數(shù)字
stack traceback:
	[C]: in function 'assert'
	test.lua:3: in local 'add'
	test.lua:6: in main chunk
	[C]: in ?

實(shí)例中assert首先檢查第一個(gè)參數(shù),若沒問題,assert不做任何事情;否則,assert以第二個(gè)參數(shù)作為錯(cuò)誤信息拋出。

error函數(shù)

語法格式:

error (message [, level])

功能:終止正在執(zhí)行的函數(shù),并返回message的內(nèi)容作為錯(cuò)誤信息(error函數(shù)永遠(yuǎn)都不會返回)

通常情況下,error會附加一些錯(cuò)誤位置的信息到message頭部。

Level參數(shù)指示獲得錯(cuò)誤的位置:

  • Level=1[默認(rèn)]:為調(diào)用error位置(文件+行號)
  • Level=2:指出哪個(gè)調(diào)用error的函數(shù)的函數(shù)
  • Level=0:不添加錯(cuò)誤位置信息

pcall 和 xpcall、debug

Lua中處理錯(cuò)誤,可以使用函數(shù)pcall(protected call)來包裝需要執(zhí)行的代碼。

pcall接收一個(gè)函數(shù)和要傳遞個(gè)后者的參數(shù),并執(zhí)行,執(zhí)行結(jié)果:有錯(cuò)誤、無錯(cuò)誤;返回值true或者或false, errorinfo。

語法格式如下

if pcall(function_name, ….) then
-- 沒有錯(cuò)誤
else
-- 一些錯(cuò)誤
end

簡單實(shí)例:

> =pcall(function(i) print(i) end, 33)
33
true
   
> =pcall(function(i) print(i) error('error..') end, 33)
33
false        stdin:1: error..
> function f() return false,2 end
> if f() then print '1' else print '0' end
0

pcall以一種"保護(hù)模式"來調(diào)用第一個(gè)參數(shù),因此pcall可以捕獲函數(shù)執(zhí)行中的任何錯(cuò)誤。

通常在錯(cuò)誤發(fā)生時(shí),希望落得更多的調(diào)試信息,而不只是發(fā)生錯(cuò)誤的位置。但pcall返回時(shí),它已經(jīng)銷毀了調(diào)用桟的部分內(nèi)容。

Lua提供了xpcall函數(shù),xpcall接收第二個(gè)參數(shù)——一個(gè)錯(cuò)誤處理函數(shù),當(dāng)錯(cuò)誤發(fā)生時(shí),Lua會在調(diào)用桟展看(unwind)前調(diào)用錯(cuò)誤處理函數(shù),于是就可以在這個(gè)函數(shù)中使用debug庫來獲取關(guān)于錯(cuò)誤的額外信息了。

debug庫提供了兩個(gè)通用的錯(cuò)誤處理函數(shù):

  • debug.debug:提供一個(gè)Lua提示符,讓用戶來檢查錯(cuò)誤的原因
  • debug.traceback:根據(jù)調(diào)用桟來構(gòu)建一個(gè)擴(kuò)展的錯(cuò)誤消息

>=xpcall(function(i) print(i) error('error..') end, function() print(debug.traceback()) end, 33) 33 stack traceback: stdin:1: in function [C]: in function 'error' stdin:1: in function [C]: in function 'xpcall' stdin:1: in main chunk [C]: in ? false nil

xpcall 使用實(shí)例 2:

function myfunction ()
   n = n/nil
end

function myerrorhandler( err )
   print( "ERROR:", err )
end

status = xpcall( myfunction, myerrorhandler )
print( status)

執(zhí)行以上程序會出現(xiàn)如下錯(cuò)誤:

ERROR: test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value)
false


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號