まとめ
- luabind で例外がキャッチできない問題が発生
- ggったら stackoverflow に解決策がヒットしたので試してみた
- 無事解決した
luabind で例外がキャッチできない
などを参考にluabind を使用して
lua 関数を呼び出してみたところ,
lua の構文エラーなどでエラーがあった場合に,
プログラムがハングしてしまう.
下記のように正しく例外処理を行っているにも関わらず.
try {
// 間違いを含む関数を呼び出す
luabind::call_function<void>(L, "Update", this);
}
catch( const luabind::error& e ) {
// 例外をキャッチできない
luabind::object errorMessage(luabind::from_stack(e.state(), -1));
std::stringstream ss;
ss << errorMessage << std::endl;
}
これでは, lua で爆速開発どころか,
構文エラーごとにハング + わけのわからないコールスタック*1に
悩ませられることになる.
いち早く解決しないと
luabind の使用を諦めざるを得ない.
とはいえ情報がない.
stackoverflow で同様の問題を見つけた
ダメ元で英語で ググったところ,
stackoverflow で同様の投稿がヒットした.神.
どうやら C++11 以降では,
デストラクタが暗黙的に
noexcept(true)
となっているらしい.
解決するためには,
自分で luabind のコードに手を入れて,
特定のデストラクタに
noexcept(false)
を設定すれば良いらしい.
解決
実際に試してみた.
修正すべきは4箇所.
- ~proxy_function_caller()
- ~proxy_function_void_caller()
- ~proxy_member_caller()
- ~proxy_member_void_caller()
すべてに
noexcept(false)
を設定すれば良い.
...
~proxy_function_caller() noexcept(false)
...
~proxy_function_void_caller() noexcept(false)
...
~proxy_member_caller() noexcept(false)
...
~proxy_member_void_caller() noexcept(false)
...
修正すべきは .hpp ファイルなので,
lib のビルドし直しなどが発生しなくて大変楽.
実際に例外を発生させてみた.
try {
// 間違いを含む関数を呼び出す
luabind::call_function<void>(L, "Update", this);
}
catch( const luabind::error& e ) {
// 問題なく例外をキャッチできた
luabind::object errorMessage(luabind::from_stack(e.state(), -1));
std::stringstream ss;
ss << errorMessage << std::endl;
}
間違いを含む lua スクリプトを渡し,
問題なく例外をキャッチできた.
無事解決.
おわりに
例外機構は遅い*2ので,できればリリース時は使いたくない.
- LUABIND_NO_EXCEPTIONS
を定義すれば 例外を投げなくなるらしいので,
十分にテストできたら Master ビルドでのみ例外のキャッチを外しても良いか?
その場合は今回手を入れた箇所ももう少し工夫しないとか?
まぁ,その時考えよう.*3