0

コード、関数を入れます。

コードは完全に機能し、永久ループはありません。

私を怒らせているのは、コンパイラの警告システムです。

コンパイラの警告では、条件が「常に False と評価される」ため、決して終了しないループがあると表示されますが、これは完全に間違っています。条件は True になる可能性があり、実行するとループ内に入って終了します。

そのような警告メッセージは無視できますが、表示されないことを望みます...コンパイラ警告システムのバグであることはわかっています。修正はありますか?

これはコードの一部です(コメントを読んで、なぜそのように書くのかを知ってください):

function DoSomethingRetrying(ReTries:Byte=3):Boolean;
var
   HasSucceeded:Boolean;
begin // Do something till not fail, retrying no more than a given number of times
     HasSucceeded:=False; // Initial value to indicate it has not yet succeeded
     repeat // Enter into the ReTry loop till not fail or had tried more than a given number of times
           Dec(ReTries); // Reduces the number of retries to ensure that the loop will end when done more than a given number of times.
           try // Just to caught some kind of error
              // Here can go a tipical AssigFile sentence
              try // Just to caught some kind of error
                 // Here can go a tipical Reset sentence
                 // Here can go a tipical Read sentence
                 try // Just to caught some kind of error
                    // Here can go some ':=' sentences to move data form the record to variables, maths, etc
                    HasSucceeded:=True; // Set the condition so the loop will end immediately.
                 except // Something went wrong
                       // Here you can put some code in case needed
                 end;
              finally // Just in case something is mandatory to be done, if failed or not.
                     // Here can go a tipical CloseFile sentence
              end;
           except // Something went wrong
                 Sleep(1); // Just make a little pause between retries
                 HasSucceeded:=DoSomethingRetrying(ReTries); // ReTry it again (with counter one less)
           end;
     until HasSucceeded or (0>ReTries); // Repeat the loop till no fail or done a max number of retries
     DoSomethingRetrying:=HasSucceeded; // Return if has succeeded
end;

実装セクションの任意のユニットにコードを(そのまま、変更せずに)追加するだけです...次にコンパイルします...警告がテキストで表示されます: W1021 Comparison always evaluates to False

コードを分析すると、次のように表示されます。

  1. False変数に入れHasSucceededます
  2. repeat...untilループの中に入る
  3. 変数を減ReTries分するため、渡された値よりも 1 少なくなります (負の可能性があります)。
  4. いくつかのブロック内で、変数tryに入れますTrueHasSucceeded
  5. そのままでは、決してそのSleep(1)部分を実行することはありません。その部分は、ほとんどの外部tryがその部分に行くexcept場合のためのものです。たとえば、AssignFile失敗した場合(ファイルが存在しないなど)
  6. until条件を評価し、HasSucceeded変数に値がTrueあり、その部分が true になることもあります(0>ReTries)(たとえばReTries、負の値がある場合)
  7. repeat...untilループを抜けます
  8. 関数は値を返しHasSucceededます (この場合はTrue)

しかし、コードの内部を深く見る必要はありません...次の文のいずれかでそれを呼び出すと想像してください: DoSomethingRetrying(0); DoSomethingRetrying(-1);

その場合untilコンディション部分(0>ReTries)は となりますTrue

コンパイラは、HasSucceeded or (0>ReTries)常に False と評価されるとどのように判断できますか?

さらに、コードを実行すると(必要に応じて段階的に)、コードが終了することがわかります。そのため、条件を評価することができます。常にTrueではありませんFalse...コンパイラの警告メッセージが表示されます!!!

それで、そのような警告メッセージタイプを非アクティブ化せずに、どうすれば回避できるのだろうかと思っていましたか?

前もって感謝します!

PD: 少なくとも、Turbo Delphi 2006 では発生します (まだ他のテストではテストされていません)。

4

2 に答える 2

14

あなたのReTries変数にByteは、符号なしの型である type があります。符号なしであるため、その値は常に 0 以上です。したがって、比較0 > Retriesは実際には常に偽です。値が負になる可能性があるというステップ 3 の主張は間違っているため、コンパイラは正しく警告します。

コンパイラのヒントや警告を無効にする前に、コンパイラが実際に間違っていることを確認してください

于 2013-03-14T15:53:49.733 に答える
2

バグではありません: コンパイラは正しい警告を発行します

その場合、until 条件部分 (0>ReTries) は True になります。

ReTries は Byte 型であるため、決して正しくありません :)

HasSucceeded:=True;

Dec(ReTries); の場合は発生しません。例外を発生させます:)

于 2013-03-14T16:01:43.117 に答える