例外処理(C++)には利点がある一方で、危険や欠点もある。
リソース解放漏れを起こしやすい
例外が送出されると、通常の処理は途中で中断される。
そのため、明示的に書いた後始末コードまで到達せず、リソース解放漏れが起こることがある。
openFile();
writeFile(); // ここで例外が送出される
closeFile(); // 実行されない同様に、newで確保したメモリも途中で例外が発生するとdeleteされないままになることがある。
このため、例外を使うコードではRAIIが重要になる。
デストラクタから例外を送出してはいけない
例外処理中のstack unwinding(スタック巻き戻し)の最中に、デストラクタ(C++)がさらに例外を送出すると、プログラムはstd::terminateされる。
そのため、デストラクタは例外を送出しないように設計する必要がある。
コストがある
例外処理にはコストがある。
- 実行ファイルサイズが増えることがある
- 例外送出時の処理は高コストになりやすい
- スタック巻き戻しには追加の処理が必要になる
特に、実際に例外が送出されたときのコストは小さくない。
制御フローが追いにくくなることがある
例外を使うと、通常の関数呼び出しだけ見ても、どこで処理が中断されてどこへ移るかが分かりにくくなることがある。
そのため、例外を多用しすぎるとコードの流れを追いにくくなる。
例外が向いていない場面もある
例外は、すべてのエラー処理に適しているわけではない。
一般に、例外が向いているのは、
- 発生頻度が低い
- 深刻で、そのまま処理を続けられない
- 発生地点では処理できない
- 戻り値などで自然に返しにくい
場合である。
逆に、よく起こる失敗や、単純な分岐で扱える失敗は、戻り値や別の手段で扱うほうが自然なことがある。
まとめ
例外処理(C++)は便利だが、
- RAIIを前提に設計する
- デストラクタ(C++)から例外を送出しない
- 例外を使うべき場面かを見極める
ことが重要である。