二重例外時の振る舞いを調べてみた。
JavaScript初心者の高木です。おはようございます。
今回、ふと思うところあって二重例外発生時の振る舞いについて調べてみることにしました。
こういう細かいところまであらかじめ理解しておくかどうかで、その言語を使う上での安心感が違います。
普段よく使っているC++では、二重例外といえばデストラクタから例外を送出した場合に起きます。
しかし、JavaScriptにはデストラクタがないので、finallyブロック内で例外を投げることで二重例外を起こすことにしました。
1 2 3 4 5 6 7 8 9 10 11 | "use strict"; try { try { throw "A"; } finally { throw "B"; } } catch (e) { process.stdout.write(e); } |
実験に使ったのは上のようなコードです。
かなり、わざとらしい例ですね。
普通はfinallyからここまで露骨に例外を投げることはないと思います。
しかし、finallyから呼び出したメソッドが例外を投げることは十分考えられます。
この実験コードを実行してみた結果、最初の例外は(実質的に)なかったことにされ、後の例外だけが処理されます。
すなわち、標準出力には「B」が出力されます。
さすがにこれはまずい気がします。
最初の例外が処理される機会を失うことで、潜在的な不具合になかなか気づかないといった弊害が予想できます。
他の言語はどうなのかもしらべてみました。
C++にはfinallyがありませんので、デストラクタから例外を送出することで二重例外を起こします。
この場合は問答無用でプログラムが異常終了します。
少なくとも最初の例外がなかったことにされるより、ずっとよい気がします。
他には、Java、C#、PHPについて調べてみました。
C#はDispose、PHPにはデストラクタがありますが、今回はすべてfinallyから例外を投げる方法で実験しました。
すると、どの言語も一貫して最初の例外がなかったことにされます。
一番後の例外だけが処理されるのです。
異なる言語間で振る舞いに一貫性があるのはよいことです。
しかし、一貫性はともかく、本当にその振る舞いでよいのでしょうか?
私は強い不安を感じますが、多くのプログラマーはそうではないんでしょうかねえ?