English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
程序运行中错误处理是必要的,在我们进行文件操作,数据转移及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]: ?
lua 里调用函数时,即使实参列表和形参列表不一致也能成功调用,多余的参数会被舍弃,缺少的参数会被补为 nil。
以上报错信息是由于参数 b 被补为 nil 后,nil 参与了 + 运算。
假如 add 函数内不是 "return a+b" 而是 "print(a,b)" 的话,结果会变成 "10 nil" 不会报错。
我们可以使用两个函数: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 (message[, level])
기능: 실행 중인 함수를 종료하고 메시지 내용을 오류 정보로 반환합니다. (error 함수는 결코 반환하지 않습니다.)
보통 error는 메시지 헤더에 오류 위치 정보를 추가합니다.
Level 매개변수는 오류 위치를 얻을지를 지정
Level=1[기본] : 호출된 error 위치(파일+행 번호)
Level=2: error 함수를 호출한 함수를 지정
Level=0: 오류 위치 정보 추가하지 않음
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..
이곳에서 반환 값을 대한 논리 판단에 유의하세요:
> function f() return false,2 end > if f() then print '1else print '0' end 0
pcall은 "보호 모드"로 첫 번째 매개변수를 호출하므로, pcall은 함수 실행 중에 발생할 수 있는 모든 오류를 잡을 수 있습니다.
오류가 발생할 때, 오류가 발생한 위치보다 더 많은 디버깅 정보를 얻고 싶습니다. 하지만 pcall이 반환될 때, 호출 스택의 일부 내용이 파괴되었습니다.
Lua는 xpcall 함수를 제공하며, xpcall은 두 번째 매개변수인 오류 처리 함수를 받아들이며, 오류가 발생할 때 Lua가 호출 스택에서 회전하기 전에 오류 처리 함수를 호출하여, 이 함수에서 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 <stdin:1> [C]: in function 'error' stdin:1: in function <stdin:1> [C]: in function 'xpcall' stdin:1: in main chunk [C]: in ? false nil
xpcall 사용 예제 2:
function myfunction () n = n/nil end function myerrorhandler( err ) print( "ERROR:", err ) end status = xpcall( myfunction, myerrorhandler ) print( status)
위 프로그램을 실행하면 다음과 같은 오류가 발생합니다:
ERROR: test2.lua:2: 객체에 수학적 연산을 시도하려고 했습니다.전역 변수 'n'는 nil 값입니다. false