编译器为什么会警告变量可能未被初始化?

4

我收到了一个编译器警告,但我不理解:

procedure Test;
var
  Var1: Integer;
begin
    while True do
    begin
        try
            if System.Random > 0.5 then
            begin
                ShowMessage('Skipping');
                continue; // If I remove this line, the warning goes away
            end;
            Var1:=6;
        except on
            E:Exception do
            begin
                ShowMessage('Error');
                raise;
            end;
        end;
        ShowMessage(IntToStr(Var1)); // Compiler warning on this line
    end;
end;

当我在Delphi 2010中编译此代码时,会出现以下警告信息:
[DCC Warning] OnlineClaimManagerMainU.pas(554): W1036 变量 'Var1' 可能未被初始化
如果我删除对 'continue' 的调用,则警告消失。
同时,如果我删除try/except子句(并保留continue),则警告也会消失。
那么,在没有初始化Var1的情况下,程序如何执行到相关代码行呢?

1
编译器的分析不如你深入。它无法确定Var1是否已被初始化。你知道Var1始终被初始化,但编译器没有你的分析能力。 - David Heffernan
那么...为什么去掉continue语句就可以解决问题呢?同样的问题将执行。还是说这两种情况的组合太过复杂而导致编译器无法处理? - awmross
在 while 前添加 Var1:=0; 以使编译器满意。 - Cesar Romero
我猜测continue的存在意味着编译器的分析更加困难。有趣的是,我曾经有一些代码,我知道它没问题,但编译器在x86中发出了警告,而在x64中却没有。我进行了明显的更改,然后x86编译器安静了下来,但x64编译器却抱怨不已!非常奇怪。 - David Heffernan
@cesar,你没有抓住重点。问题是为什么编译器会警告永远不会发生的事情。 - David Heffernan
3个回答

4
Var1将始终在使用之前进行初始化。编译器会因try-except处理而感到困惑:您的代码对于编译器来说过于复杂,以至于无法确定Var1是否始终被初始化。它看到在Var1:=6;之前可能会有一个已处理的异常,这将使Var1未初始化,但它没有看到该异常将始终被重新引发。

它不会自动初始化本地未管理的变量。 - Cesar Romero
@Cesar hvd 表示始终在使用之前初始化。 - David Heffernan

0

你应该将ShowMessage(IntToStr(Var1));放入try except块中。 这样编译器就可以清楚地知道Var1已初始化,且代码更为清晰。


1
这样做意味着,如果ShowMessage引发异常(是的,它可以这样做,而且我假设它是从调用不仅仅是ShowMessage的代码简化而来),异常处理程序将运行,而在问题中的代码中则不会。 - user743382

0

这是一个相当好的警告。它告诉你不要给变量分配任何值,因为它可能在代码的其他地方使用。警告还告诉你,如果使用它,则分配给它的值可能不是你所期望的。


1
我认为你没有理解这个问题。 - Rob Kennedy
@Rob Kennedy,我认为你误解了我的回答。在路径中没有将值分配给Var1,因此会出现警告。如果您不同意,请在评论中添加一些价值。 - Rob
1
非常好。问题并没有问这个警告意味着什么。它问的是为什么在这种情况下会发出警告,特别是因为看似不相关的更改会影响警告的出现。对人类来说,Var1确实在警告指示的点上被赋值了,但编译器却看不到这一点。你的回答表明你认为这个警告是正确的,请展示一下如何正确。 - Rob Kennedy
1
我现在明白了,对ShowMessage(IntToStr(Var1))的调用只有在给Var1赋值时才会执行。因此,这个警告实际上没有意义。 感谢Rob K.的友善帮助让我弄清楚了这一点。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接