「変数が初期化されていない可能性」警告の理由がわからない

解決


T2  2016-09-22 01:02:32  No: 48332

環境はWindows7、Delphi XEです。 

下記のようなプログラムで
「変数 'c' が初期化されていない可能性があります」
と警告が出ます。

procedure test(a, b: integer);
var
  i: Integer;
  c: Integer;
begin
  for i := 1 to a do begin
    if b = 1 then begin
      c := 1;
    end else begin
      Exit;
    end;
    if c = 1 then begin
      Exit;
    end;
  end;
end;

if c = 1 then begin
に到達する際には必ずc := 1で初期化されているはずだと思うのですが、何が問題なのでしょうか。
ちなみに、forの条件のaを変数ではなくリテラル値にすると警告がなくなりますが、それも何故なのかわかりません。

動作上は警告を無視しても問題ないみたいなのですが、原因がわからなくて気持ち悪い感じです。
よろしくお願いします。


Mr.XRAY  2016-09-22 02:25:19  No: 48333

>「変数 'c' が初期化されていない可能性があります」 

変数 c の値が決まらない場合があるということですね.
提示のコードだと,b が 1 ではないときに発生するのでは ?
Exit していますから.

>forの条件のaを変数ではなくリテラル値にすると警告がなくなりますが、

??
リテラルにしたらエラーになるのでは ?

間違っていたらゴメンナさい.


Mr.XRAY  2016-09-22 02:35:29  No: 48334

>リテラルにしたらエラーになるのでは ? 
>
>間違っていたらゴメンナさい.

スミマセン.整数のリテラルのことですね.
残念ですが分かりません.


tor  2016-09-22 06:30:31  No: 48335

人間がコードをたどってみれば確かに、cが初期化されるかその前に抜けるかのどちらかであるとわかりますが
こういったケースも含めて、初期化されるかどうか判定するアルゴリズムを作るのは大変困難です。
(ちなみに「プログラムの停止性問題」と言って、どんなコードも確実に判定できる万能アルゴリズムは存在し得ないと数学的に証明されています)

もちろん頑張ればこういうケースも考慮に入れてアルゴリズムを改良することも可能でしょうが
コンパイラのお仕事はあくまでコードをコンパイルすること。
未初期化変数の検出といったことはそのついでにやってくれる、いわばサービスなので
そこを完璧にするために労力を注ぎ込むのは本末転倒だ……ということで納得してはどうでしょうか。
(実際、本当に初期化されないかどうか確実には言えないので
「可能性があります」という言い方になってますよね)

警告が出るのがどうしても気持ち悪ければ、例えば今回のケースなら
 c := 1;
 if b <> 1 then Exit;
と、間違いなく初期化されていると判定できるようにコードを書き換えるというのもありではないでしょうか。


T2  2016-09-24 00:36:44  No: 48336

返信が遅くなってしまい申し訳ありません。

プログラムの停止性問題というのは初耳でした。

初期化位置が
c := 1;
if b <> 1 then Exit; 
だと今度は「'c' に代入された値は使われていません」が発生してしまうため、
c := 1;
for i := 1 to a do begin
のようにしました。

Mr.XRAYさん、torさん、ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加