戻り値と例外
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2022/06/21 21:57 UTC 版)
例外処理(例外オブジェクト)をサポートしないCなどの言語では、従来から関数(サブルーチン)の戻り値によってその関数(処理)の成否を判定する方法がとられてきた。慣例的に、関数の戻り値を32ビット整数値などで宣言して、関数が成功した場合は0を返し、失敗した場合はエラーコードとして何らかの負数を返すことが多い。さらに簡略化して、成否の結果を真偽値1/0で返すだけにすることもある。戻り値がポインタ型である場合は、成功した場合に有効なポインタすなわち非NULLを返し、失敗した場合に無効なポインタすなわちNULLを返すのが通例である。標準ライブラリや各種APIでは、詳細を伝えるエラーコードを別途errnoのようなグローバル変数に格納することもある。各エラーコードによって失敗の原因を定義しておき、呼び出し側で原因を判定する。 このような戻り値による処理の成否判定には下記のような問題点がある。 戻り値は無視できるため、呼び出し先でエラーが発生しても通常通り処理を継続するプログラムを記述できてしまう。 エラーコードはたいてい32ビットの整数値でしかないため、それ以上の詳細な情報(例えば具体的原因および異常発生個所などを示すエラーメッセージ)を付加することができない。直前のエラー情報をグローバル変数に格納する設計は、マルチスレッド対応の際に別途スレッドローカルストレージ化が必要となる。 戻り値を毎回チェックする判定文を記述するのが煩雑である。 戻り値に正常系の値と異常系の値(エラー判定用の値)とを混在させる、あるいは正常系と異常系とで戻り値の区別がつかない関数は、関数呼び出し結果の戻り値を式の中でそのまま使えなくなってしまう。 3. に関連する問題として、戻り値が正常系の結果取得に使えないため引数を処理結果の取得用に使い関数インターフェイスおよび呼び出し側のコードが複雑化するという問題がある。 bool countPositiveElements(const double x[], int inNumberOfElements, int* outNumberOfElements) { if (x == NULL || inNumberOfElements <= 0 || outNumberOfElements == NULL) { return false; // 異常終了。 } *outNumberOfElements = 0; for (int i = 0; i < inNumberOfElements; ++i) { if (!isnan(x[i]) && x[i] > 0) { (*outNumberOfElements)++; } } return true; // 正常終了。} 4.の問題では関数の呼び出し結果をいったんローカル変数に格納することなく次の関数引数にそのまま式として渡すようなこともできなくなる。例えば下記のC言語の例では、atof()関数の戻り値が正常系と異常系とで区別がつかない仕様のため、対象フォーマット外の不正な入力があっても検知できず処理を継続してしまう。例外を使わずにこの問題に対処するには、正常系と異常系とを区別できるようにするために、関数の実装およびインターフェイスが複雑化することを許容しなければならない。 #include
※この「戻り値と例外」の解説は、「例外処理」の解説の一部です。
「戻り値と例外」を含む「例外処理」の記事については、「例外処理」の概要を参照ください。
- 戻り値と例外のページへのリンク