ゲーム開発

【Lua】エラー処理の書き方

Luaには他の言語でよくあるtry~の例外処理が存在しない代わりに、pcall/xpcallというエラー処理用の関数が標準で用意されています。

この記事では、pcall/xpcallの使い方とサンプルコード、それと、おまけで自作エラーの作り方とサンプルコードをまとめています。

Luaでのエラー処理の書き方

Luaでエラー処理を行う場合は、pcall()またはxpcall()を使用します
pcall/xpcall内では、Luaがprotected modeで実行される仕組みのため、エラーが発生してもpcall/xpcall内でキャッチされます

pcall()とxpcall()の違いは、メッセージハンドラを使用するかどうかの違いです。
メッセージハンドラにはトレース情報等を使用できるため、トレース情報等を使う場合はxpcall()を使います。
通常のエラーメッセージのみの場合はpcall()で十分です。

pcallの場合

pcall()は以下の形式で呼び出します。
pcall(<エラーが起きる可能性のある関数>, [関数の引数1], [関数の引数2], ...)

エラーの発生有無はpcallの返り値で判断できます。

エラー発生有エラー発生無
1つ目の返り値falsetrue
2つ目の返り値エラーメッセージ関数の実際の返り値
(複数の返り値がある場合は3つ目、4つ目…に設定される)


エラー発生有/無それぞれのサンプルコードは以下です。

-- エラーが発生する関数の例 (引数が'abc'以外の場合にエラー)
function hogeFunction(str)
    if str ~= 'abc' then
        error('DUMMY ERROR')
    end
    return 'ABC'
end


-- エラーが発生しない呼び出しの場合
pcallResult, functionReturn = pcall(hogeFunction, 'abc')

-- 1つ目の返り値にtrue、2つ目以降の返り値に指定した関数の実際の返り値が設定される
print(pcallResult .. ', ' .. functionReturn)
-- > true, ABC


-- エラーが発生する呼び出しの場合
pcallResult, functionReturn = pcall(hogeFunction, '123')

-- 1つ目の返り値にfalse、2つ目の返り値にエラーメッセージが設定される
print(pcallResult .. ', ' .. functionReturn)
-- > false, [string "GEConsole"]1:1 DUMMY ERROR

xpcallの場合

xpcall()は以下の形式で呼び出します。
xpcall(<エラーが起きる可能性のある関数>, <メッセージハンドラ>, [関数の引数1], [関数の引数2], ...)

メッセージハンドラを指定する以外はpcall()と同じであるため、返り値等の説明は省略します。

Lua標準のdebug.tracebackをメッセージハンドラに指定する場合のサンプルコードを以下に示します。

-- エラーが発生する関数の例 (引数が'abc'以外の場合にエラー)
function hogeFunction(str)
    if str ~= 'abc' then
        error('DUMMY ERROR')
    end
    return 'ABC'
end


-- エラーが発生しない呼び出しの場合
xpcallResult, functionReturn = xpcall(hogeFunction, debug.traceback, 'abc')

-- 1つ目の返り値にtrue、2つ目以降の返り値に指定した関数の実際の返り値が設定される
print(xpcallResult .. ', ' .. functionReturn)
-- > true, ABC


-- エラーが発生する呼び出しの場合
xpcallResult, functionReturn = xpcall(hogeFunction, debug.traceback, '123')

-- 1つ目の返り値にfalse、2つ目の返り値にエラーメッセージが設定される
print(pcallResult .. ', ' .. functionReturn)
-- > false, debug.tracebackの中身(↓参照)
debug.tracebackをメッセージハンドラにした場合は↑のような出力になります。

自作のエラーを発生させる方法

上のサンプルコードでしれっと書いていましたが、LuaでもPythonのraiseのように自分でエラーを発生させることが可能です。


自分でエラーを発生させる場合はerror()を使用します。
error()を呼び出すとその時点でエラーが発生し(前述のpcall/xpcallでキャッチしない場合)、プログラムが終了します。


error()は以下の形式で呼び出します。
error(<エラーメッセージ>, [エラー情報の階層])


なお、エラーメッセージには自動的に行数等の情報が付与されます。

例えば
error('DUMMY ERROR')
という呼び出しを行った場合、エラーメッセージは
'[string "GEConsole"]1:1 DUMMY ERROR'
となります。
※付与される情報は環境によって異なります。

付与される情報はerror()の第二引数で変更可能です。

デフォルトは1となっており、1の場合はerror()を呼び出した行数等がエラーメッセージに付与されます。
2を指定した場合は、error()を呼び出した関数を呼び出した箇所がエラーメッセージに付与されます。
後はご想像の通り、3, 4…と指定する数が大きいほど呼び出しが上の階層の情報が付与されます。

なお、0を指定した場合は情報の付与が行われません


上の章で登場済みですが、一応ここにもサンプルコードを置いておきます。

-- エラーが発生する関数の例 (引数が'abc'以外の場合にエラー)
function hogeFunction(str)
    if str ~= 'abc' then
        error('DUMMY ERROR')
        -- エラーメッセージは、"↑の行数等の情報 + DUMMY ERROR"
    end

    return 'ABC'
end


-- エラーメッセージに行数等の情報を付与したくない場合
function hogeFunction2(str)
    if str ~= 'abc' then
        error('DUMMY ERROR', 0)
        -- エラーメッセージは、"DUMMY ERROR"のみ
    end

    return 'ABC'
end

参考

https://www.lua.org/manual/5.4/manual.html#2.3
https://www.lua.org/manual/5.4/manual.html#pdf-pcall
https://www.lua.org/manual/5.4/manual.html#pdf-xpcall
https://www.lua.org/manual/5.4/manual.html#pdf-error
https://www.lua.org/manual/5.4/manual.html#pdf-debug.traceback

コメント

タイトルとURLをコピーしました