【问题标题】:How to get rid of compiler warning confused by `continue`? [duplicate]如何摆脱由“继续”混淆的编译器警告? [复制]
【发布时间】:2016-03-01 14:08:51
【问题描述】:

编译器向我显示以下代码的以下警告:

Warning: W1036 Variable 'Address' might not have been initialized

代码(一个基于真实代码的MVCE sn-p):

function DoFoo(): Integer;
var
  i: Integer;
  Address, Bar: Cardinal;
begin
  for i := 1 to 5 do
  begin
    try
      Address := Hex2CardPos(IntToStr(i));
    except on EConvertError do
      continue;
    end;
    Bar := Address + 42;  // "Warning: Address might not have been initialized"
  end;
  Result := 42;
end;

如您所见,Address 是:

  1. 分配给Hex2CardPos()的结果
  2. Hex2CardPos() 抛出错误并立即跳过循环迭代。

我试图通过在循环的开头添加一个无用的Address := 0; 来解决此问题,但随后警告被替换为另一个:

Hint: H2077 Value assigned to 'Address' never used.

这是编译器错误还是警告有实质内容?

【问题讨论】:

  • TryHex2CardPos 函数会让你的生活在这里变得更轻松
  • @DavidHeffernan 如果错误输入触发EConvertError,这个函数会返回什么?让它引发异常并让处理程序处理它似乎最干净。
  • 如果您希望定期处理错误的输入数据,那么通过布尔值指示成功或失败的版本通常比使用异常的版本更干净。一般来说,如果您想在异常处理程序中包装单个低级函数调用,则该函数设计不佳。见StrToIntTryStrToInt
  • 它显然会返回False,就像TryStrToInt一样。像这样使用它:if TryHex2CardPos(IntToStr(i), Address) then Bar := Address + 42。这将使警告消失,但主要是因为编译器的数据流分析忽略了var 参数;它假定所有var 参数总是被分配。
  • 我的意思是,编译器在发出警告时存在缺陷,这是一个好问题。虽然我确实相信我以前见过它,所以它可能是一个骗局。 (你去吧,我找到了骗子,并相应地标记了它。)但这是一个好问题。我只是提供我认为是编写代码的更好方法。

标签: delphi delphi-xe2 compiler-warnings


【解决方案1】:

问题出在您的代码中。 "Bar" 赋值必须在 try except 块中,因为当异常发生时你不想赋值 "Bar"

function DoFoo(): Integer;
var
  i: Integer;
  Address, Bar: Cardinal;
begin
  for i := 1 to 5 do
  begin
    try
      Address := Hex2CardPos(IntToStr(i));
      Bar := Address + 42;
    except on EConvertError do
      continue;
    end;
  end;
  Result := 42;
end;

顺便说一句,这段代码有一个正确的"H2077 Value assigned to 'Bar' never used"

【讨论】:

  • 哈!所以就是这样。我遵循的一般规则是尽可能多地隔离我打算捕获其异常的代码(即try 块中的代码)。感谢您的回答
  • 仅仅因为您确定了使警告消失的代码排列并不意味着问题出在代码中。编译器确实错了;您已经确定了一个解决方法。编译器应该能够在原始代码中识别出没有跳过Address 赋值的Bar 赋值路径。
  • 同意。这里的编译器有缺陷。
猜你喜欢
  • 2020-08-25
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
相关资源
最近更新 更多