2014年2月15日土曜日

absの罠

こないだ、@kumagiさんがJubatusのクラスタリングのテスト書いたらNaNになるというので、デバッグしてたらabsにハマってたという恐ろしいバグを発見したので書いておきます。

C++で絶対値を求める関数は3つあります。

  • ::abs Cの関数でintを引数に取る
  • ::fabs Cの関数でdoubleを引数に取る
  • std::abs C++の関数でint引数とdouble引数でオーバーロードされている

さて、大事なのは std::abs はオーバーロードされているので、doubleを渡すと::fabs相当の処理をしてくれる、ところが::absはCの関数なのでdoubleを渡してdoubleで結果を受け取ろうとすると、intにキャストして絶対値を計算してからdoubleに戻す、という恐ろしい挙動を示すことです。さて、std::absを呼んでるつもりで、absと書くとどうなるか。usingしていればもちろんstd::absになりますが、そうでない場合には::absになる可能性があります。すると、渡されたdobule値はintにキャストされて、華麗にオーバーフローして、もう残りは目も当てられません。 素直にfabsを使うか、absを使うときは必ずstd::absと面倒でも明示的に書くのがいいようです。不正確なabsという書き方はほんとうに怖いので、grep "[^:f]abs(" で簡単にチェックできるので、活用するのをおすすめします。

サンプルコード

2 件のコメント:

  1. スマホ 画面 録画 のガイドを活用して、デバイスの可能性を解き放ちましょう! チュートリアルでも、思い出に残る瞬間のキャプチャでも、この機能は多用途のツールです。 画面アクティビティを簡単に記録して共有する手順を学びましょう。

    返信削除