コード、関数を入れます。
コードは完全に機能し、永久ループはありません。
私を怒らせているのは、コンパイラの警告システムです。
コンパイラの警告では、条件が「常に 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
に入れますTrue
HasSucceeded
- そのままでは、決してその
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 では発生します (まだ他のテストではテストされていません)。