閑古鳥

オールドプログラマの日記。プログラミングとか病気(透析)の話とか。

数学関数のエラーを処理する _matherr 関数

数学関数の引数に不正な値を与えるとエラーが発生しますが、_matherr関数を定義するとエラーが発生する直前に処理することができます。

注:以下の記述はBorland C++ Compilerにて確認を行っています。環境によっては関数名や定数名が違ったり(gccではアンダースコアが付かない?)、また_matherr関数の上書きができない場合もあります(らしい)ので、試す場合は使用している環境のマニュアルの方も参照してください。

_matherr関数は次のように宣言されています。

int _matherr(struct _exception* e);

戻り値に0以外の値を返すと、処理系で実装されている規定の動作(大抵エラーメッセージが表示される)が行われなくなりますので、自前で用意したエラーメッセージのみを表示させることもできます。

引数の構造体のメンバは以下のようになっており、エラーの詳細を得ることができます。

struct _exception {
  int   type;  // エラーの種別
  char  *name; // エラーが発生した関数の名前
  double arg1, arg2, retval; // 引数と、エラーが発生した関数の戻り値
};

arg2は引数が単一の時は使用されません。また、retvalを_matherr関数内で上書きすると、エラーが起こった時の戻り値を変更することができます。

typeの内訳は以下の通り。それぞれmath.hに定義されています。

DOMAIN
引数が範囲外
SING
引数が無効
OVERFLOW
オーバーフロー
UNDERFLOW
アンダーフロー
TLOSS
有効桁数が失われた

以下のような感じでデフォルトのエラーを出力させず、自前のメッセージを表示させることができるようになります。

#include <iostream>
#include <cmath>
using namespace std;

int _matherr(struct _exception* e) {
    cout << "error message..." << endl;
    return 1; // 0以外の値を返すと規定の動作を行わなくなる
}

int main()
{
    sqrt(-1.0); // SQRT Domain Error
    return 0;
}