Lua エラー処理

プログラム実行中にはエラー処理が必要です。ファイル操作、データ転送、Webサービス呼び出しの過程では、予期しないエラーが発生する可能性があります。エラー情報の処理を軽視すると、情報漏洩やプログラムの実行不能などの状況を引き起こす可能性があります。

どのプログラム言語でも、エラー処理が必要です。エラーの種類には次のものがあります:

  • 構文エラー
  • 実行時エラー

構文エラー

構文エラーは通常、プログラムの構成要素(演算子、式など)の不適切な使用によって引き起こされます。簡単な例は次のとおりです:

-- test.lua 文件
a == 2

上記のコードの実行結果は次のとおりです:

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

ご覧のとおり、上記では構文エラーが発生しています。「=」1つと「==」2つには違いがあります。「=」1つは代入式で、「==」2つは比較演算です。

もう1つの例:

例

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 の2つの関数を使用できます。例は次のとおりです:

例

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は2番目のパラメータをエラー情報としてスローします。

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..
> function f() return false,2 end
> if f() then print '1' else print '0' end
0

pcallは「保護モード」で最初のパラメータを呼び出すため、pcallは関数実行中のあらゆるエラーをキャッチできます。

通常、エラー発生時には、エラーが発生した位置だけでなく、より多くのデバッグ情報を得たいものです。しかし、pcallが戻るとき、呼び出しスタックの一部の内容はすでに破棄されています。

Luaはxpcall関数を提供しています。xpcallは2番目のパラメータとしてエラー処理関数を受け取ります。エラーが発生すると、Luaは呼び出しスタックが展開(unwind)される前にエラー処理関数を呼び出します。これにより、この関数内でdebugライブラリを使用してエラーに関する追加情報を取得できます。

debugライブラリは2つの一般的なエラー処理関数を提供しています:

  • 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: attempt to perform arithmetic on global 'n' (a nil value)
false
その他の拡張