どせいたんさき。

ナスダヨー

SLLIB-1.4.0, SFITSIO-1.4.0 の導入でハマった件

症状

コンパイルでは問題なかった.ダウンロードしてきた tar.gz ファイルを展開.MakefileCFLAGS-m64 を設定して make && make install64 すれば SLLIB も SFITSIO もインストールはできた.

問題が起こったのは実際に自分のプログラムで使おうとしたとき.コンパイルしようとすると.

'isfinite' was not declared in this scope

という感じのエラーが出た.

なお,使用しているコンパイラは g++ でバージョンは以下のとおり.

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

問題

エラーが出たあたりのソースを見ると isfinitestd:: などなしにそのまま記述してある.インクルード元だと思われるヘッダファイル math.h を見てみる.isfinite#define マクロとして定義されている.

/* Return nonzero value if X is not +-Inf or NaN.  */
# ifdef __NO_LONG_DOUBLE_MATH
#  define isfinite(x) \
     (sizeof (x) == sizeof (float) ? __finitef (x) : __finite (x))
# else
#  define isfinite(x) \
     (sizeof (x) == sizeof (float)                                            \
      ? __finitef (x)                                                         \
      : sizeof (x) == sizeof (double)                                         \
      ? __finite (x) : __finitel (x))
# endif

自分のプログラムを見ると cmath をインクルードしていた.このヘッダファイルをみてみると

// These are possible macros imported from C99-land.
#undef fpclassify
#undef isfinite
#undef isinf
#undef isnan
#undef isnormal
#undef signbit
#undef isgreater
#undef isgreaterequal
#undef isless
#undef islessequal
#undef islessgreater
#undef isunordered

ということで #undef していた.そのせいでエラーが発生していたようである.

暫定的な解決方法

cmath を使わずに math.h だけ使用する……というのがひとつの解決策.ただし,cmath を使用する機会はあるのではないかという気がしたので SLLIB, SFITSIO をちょっと書き換える.

具体的には grep コマンドで isfinite を使用しているソース,ヘッダファイルを同定して s/isfinite/std::isfinite/で置換した.また, math.h をインクルードしているヘッダファイルでは並行して cmath もインクルードするようにした.


この方法で自分の作成していたプログラムはとりあえず動作するようになった.しかし,cmath では他にもいろいろなマクロを #undef している.同種の問題は他の場所でも起こりうるかもしれないので,今回の対応を忘れないようにしたい.