コード、関数を入れます。
コードは完全に機能し、永久ループはありません。
私を怒らせているのは、コンパイラの警告システムです。
コンパイラの警告では、条件が「常に 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
コードを分析すると、次のように表示されます。
False変数に入れHasSucceededますrepeat...untilループの中に入る- 変数を減
ReTries分するため、渡された値よりも 1 少なくなります (負の可能性があります)。 - いくつかのブロック内で、変数
tryに入れますTrueHasSucceeded - そのままでは、決してその
Sleep(1)部分を実行することはありません。その部分は、ほとんどの外部tryがその部分に行くexcept場合のためのものです。たとえば、AssignFile失敗した場合(ファイルが存在しないなど) until条件を評価し、HasSucceeded変数に値がTrueあり、その部分が true になることもあります(0>ReTries)(たとえばReTries、負の値がある場合)repeat...untilループを抜けます- 関数は値を返し
HasSucceededます (この場合はTrue)
しかし、コードの内部を深く見る必要はありません...次の文のいずれかでそれを呼び出すと想像してください:
DoSomethingRetrying(0);
DoSomethingRetrying(-1);
その場合untilコンディション部分(0>ReTries)は となりますTrue。
コンパイラは、HasSucceeded or (0>ReTries)常に False と評価されるとどのように判断できますか?
さらに、コードを実行すると(必要に応じて段階的に)、コードが終了することがわかります。そのため、条件を評価することができます。常にTrueではありませんFalse...コンパイラの警告メッセージが表示されます!!!
それで、そのような警告メッセージタイプを非アクティブ化せずに、どうすれば回避できるのだろうかと思っていましたか?
前もって感謝します!
PD: 少なくとも、Turbo Delphi 2006 では発生します (まだ他のテストではテストされていません)。