Menu

for文の継続条件について

Anonymous
2012-09-29
2012-10-22
  • Anonymous

    Anonymous - 2012-09-29

    AdLintについて2点ほどご報告です.
    下記のコードを解析すると,6行目のfor文の継続条件に対して4つの警告メッセージが出ました(AdLint 2.4.0,Ubuntu 12.04).

    int main(void)
    {
      const int nchildren = 1;
      int inf = 0;
      int i;
      for (i = 0; (inf != 0) && (i < nchildren); i++)
      {
        inf++;
      }
      return 0;
    }
    
    W,../side.c,6,20,W0609,この論理演算の結果は常に真になります。
    W,../side.c,6,32,W0610,この論理演算の結果は常に偽になります。
    W,../side.c,6,26,W0610,この論理演算の結果は常に偽になります。
    W,../side.c,6,26,W0088,論理演算子の右側の式は、副作用がない冗長な式です。
    

    1点目に,最初の3つがコードと矛盾しています.これはもしかすると,W0100を避けるため2回以上のループを仮定したことによる影響でしょうか?

    2点目に,4つ目の警告 W0088 がfor文の継続条件に検知されるのは違和感を感じます.

    以上です.

     
    • Yutaka Yanoh

      Yutaka Yanoh - 2012-10-22

      ご報告ありがとうございます。

      申し訳ありません。本件も AdLint の不具合でした。

      ご指摘の通りループが 2 回以上回ると仮定したことと、for 文の評価方法に問題がありました。

      AdLint での for 文の評価方法は下記のようになっています。

      int main(void)
      {
        const int nchildren = 1;
        int inf = 0;
        int i;
      
        /* (1) for 文中で i と inf が更新されるので、i と inf を制御変数と認識 */
        /* (2) i は増加方向に更新されることから、i >= 0 の値を取り得ると仮定 */
        /* (3) inf は増加方向に更新されることから、inf >= 0 の値を取り得ると仮定 */
        /* (4) 制御式 (inf != 0) && (i < nchildren) の評価結果から for 文本体がデッドコードであるかを確認 */
        /* (5) デッドコードではないループは 2 回以上回るという仮定から、(inf != 0) && (i < nchildren) が真となるように制御変数値の定義域を調整 */
        /* (5-1) (2) の定義域をもとに i < nchildren となるよう調整し、i == 0 となる */
        /* (5-2) (3) の定義域をもとに inf != 0 となるよう調整し、inf > 0 となる */
        for (i = 0; (inf != 0) && (i < nchildren); i++)
        {
          inf++; /* (6) inf の定義域が > 1 となる */
          /* (7) for 文先頭の i++ で i の定義域が == 1 となる */
          /* (8) 次のループに入り、(inf != 0) && (i < nchildren) を評価 */
          /* (8-1) (6) で inf > 1 となっていることから、inf != 0 は常に真と警告 */
          /* (8-2) (7) で i == 1 となっていることから、i < nchildren は常に偽と警告 */
          /* (8-3) && の右辺 (8-2) が常に偽なので、&& 式も常に偽と警告 */
        }
        return 0;
      }
      

      今回の問題は (8) で制御式を再評価する部分にあり、消極的な対応方法ですが、制御式の再評価時には W0609 / W0610 コードチェックを実行しないようにしました。
      この修正を AdLint 2.6.0 に盛り込み、本日リリースいたしました。

      お手数おかけしますが、AdLint 2.6.0 にアップデートしていただき、再度ご確認をお願いいたします。

      今後も制御構造の抽象化方法について検討し、随時改良していきたいと思います。


      後半の W0088 警告の件ですが、こちらも AdLint の不具合でした。

      W0088 警告は、if 文と同等のロジックを短絡評価を利用して式文として記述するようなケースで、誤って論理式の右辺に副作用が無い式を置いたことを指摘するものです。
      単独の式文であることの判定があまく、for 文の条件式部分についてもチェックが走ってしまっていました。

      この修正も AdLint 2.6.0 に盛り込みました。あわせてご確認をお願いいたします。

       
  • Anonymous

    Anonymous - 2012-10-22

    ご対応ありがとうございます.
    AdLint 2.6.0 で上記の警告が出なくなったことを確認いたしました.

     

Anonymous
Anonymous

Add attachments
Cancel