雖然你可以使用任何類型的值作為錯誤信息,通常情況下,我們使用字符串來描述遇到的錯誤。如果遇到內部錯誤(比如對一個非table的值使用索引下標訪問)Lua將自己產生錯誤信息,否則Lua使用傳遞給error函數的參數作為錯誤信息。不管在什么情況下,Lua都盡可能清楚的描述問題發生的緣由。
local status, err = pcall(function () a = 'a'+1 end)
print(err)
--> stdin:1: attempt to perform arithmetic on a string value
local status, err = pcall(function () error("my error") end)
print(err)
--> stdin:1: my error
例子中錯誤信息給出了文件名(stdin)與行號。
函數error還可以有第二個參數,表示錯誤發生的層級。比如,你寫了一個函數用來檢查“error是否被正確調用”:
function foo (str)
if type(str) ~= "string" then
error("string expected")
end
...
end
可有人這樣調用此函數:
foo({x=1})
Lua會指出發生錯誤的是foo而不是error,實際上,錯誤是調用error時產生的。為了糾正這個問題,修改前面的代碼讓error報告錯誤發生在第二級(你自己的函數是第一級)如下:
function foo (str)
if type(str) ~= "string" then
error("string expected", 2)
end
...
end
當錯誤發生的時候,我們常常希望了解詳細的信息,而不僅是錯誤發生的位置。若能了解到“錯誤發生時的棧信息”就好了,但pcall返回錯誤信息時,已經釋放了保存錯誤發生情況的棧信息。因此,若想得到tracebacks,我們必須在pcall返回以前獲取。Lua提供了xpcall來實現這個功能,xpcall接受兩個參數:調用函數、錯誤處理函數。當錯誤發生時,Lua會在棧釋放以前調用錯誤處理函數,因此可以使用debug庫收集錯誤相關信息。有兩個常用的debug處理函數:debug.debug和debug.traceback,前者給出Lua的提示符,你可以自己動手察看錯誤發生時的情況;后者通過traceback創建更多的錯誤信息,也是控制臺解釋器用來構建錯誤信息的函數。你可以在任何時候調用debug.traceback獲取當前運行的traceback信息:
print(debug.traceback())