为什么dcc64说这个值从未使用过?

时间:2017-01-18 22:29:25

标签: delphi 64-bit

以下代码来自DDetours.pas。当它编译为32位时,没有发出警告。当它编译为64位时,它会发出此警告:(Delphi Berlin Update 2)

[dcc64 Hint] DDetours.pas(1019): H2077 Value assigned to 'Prf' never used

这是有问题的功能

function GetPrefixesCount(Prefixes: WORD): Byte;

var
  Prf: WORD;
  i: Byte;
begin
  { Get prefixes count used by the instruction. }
  Result := 0;
  if Prefixes = 0 then
    Exit;

  Prf := 0;
  i := 0;
  Prefixes := Prefixes and not Prf_VEX;
  while Prf < $8000 do
  begin
    Prf := (1 shl i);
    if (Prf and Prefixes = Prf) then
      Inc(Result);
    Inc(i);
  end;
end;

在我看来,Prf首次与使用初始值的8000美元进行比较时确实很好。

3 个答案:

答案 0 :(得分:2)

怀疑 64位编译器内置少量智能,以便识别

  • 变量已初始化,在输入循环之前不会再次触摸。
  • 循环条件是将变量与文字进行比较。
  • 初始值0满足循环条件,从而确保循环在运行时始终至少运行一次,从而有效地使其像repeat..until循环一样。

由于编译器仍然必须为初始化生成代码,但是知道在运行时不需要初始值来进入循环,它可以发出警告,初始值将不被使用。

如果不初始化变量,编译器在编译时不知道是否输入循环,因为行为未定义,因此编译器会发出有关未初始化变量的不同警告。 / p>

查看反汇编,您可以看到循环变为repeat..until循环,并且优化删除了Prf := 0;分配:

Project87.dpr.17: Result := 0;
00000000004261AA 4833D2           xor rdx,rdx
Project87.dpr.18: if Prefixes = 0 then
00000000004261AD 6685C0           test ax,ax
00000000004261B0 7460             jz GetPrefixesCount + $72
Project87.dpr.22: i := 0;
00000000004261B2 4D33C0           xor r8,r8
Project87.dpr.23: Prefixes := Prefixes and not Prf_VEX;
00000000004261B5 0FB7C0           movzx eax,ax
00000000004261B8 81E02DFBFFFF     and eax,$fffffb2d
00000000004261BE 81F8FFFF0000     cmp eax,$0000ffff
00000000004261C4 7605             jbe GetPrefixesCount + $2B
00000000004261C6 E8050FFEFF       call @BoundErr
Project87.dpr.26: Prf := (1 shl i);
00000000004261CB 41C7C101000000   mov r9d,$00000001
00000000004261D2 418BC8           mov ecx,r8d
00000000004261D5 41D3E1           shl r9d,r9b
00000000004261D8 4489C9           mov ecx,r9d
00000000004261DB 81F9FFFF0000     cmp ecx,$0000ffff
00000000004261E1 7605             jbe GetPrefixesCount + $48
00000000004261E3 E8E80EFEFF       call @BoundErr
Project87.dpr.27: if (Prf and Prefixes = Prf) then
00000000004261E8 448BC9           mov r9d,ecx
00000000004261EB 664423C8         and r9w,ax
00000000004261EF 66443BC9         cmp r9w,cx
00000000004261F3 750A             jnz GetPrefixesCount + $5F
Project87.dpr.28: Inc(Result);
00000000004261F5 80C201           add dl,$01
00000000004261F8 7305             jnb GetPrefixesCount + $5F
00000000004261FA E8F10EFEFF       call @IntOver
Project87.dpr.29: Inc(i);
00000000004261FF 4180C001         add r8b,$01
0000000000426203 7305             jnb GetPrefixesCount + $6A
0000000000426205 E8E60EFEFF       call @IntOver
Project87.dpr.24: while Prf < $8000 do
000000000042620A 6681F90080       cmp cx,$8000
000000000042620F 72BA             jb GetPrefixesCount + $2B 

答案 1 :(得分:1)

好吧,我想答案是dcc64在消息方面是一个错误的编译器。因为如果您注释掉违规行,那么#34;值从未使用过&#34;变得&#34;可能没有被初始化。&#34;相同的编译器。

[dcc64 Warning] DDetours.pas(1022): W1036 Variable 'Prf' might not have been initialized

答案 2 :(得分:1)

这是一个编译错误。这种性质有一些。相当令人沮丧。有时32位编译器会以不合理的方式抱怨,然后当您解决时,64位编译器反过来以一种不合理的方式抱怨您的解决方法。

我不认为Embarcadero习惯性地使用提示和警告进行编译,因为他们的库代码充满了提示和警告。

无论如何,在这种情况下,编译器会看到对变量的两次写入,但由于某种原因无法识别变量的介入读取。

你可以做的事情不多。您可以提交错误报告。我希望您不想更改代码,因为它是第三方代码。如果你不改变它,那么你将不得不忍受伪造的暗示。

通知图书馆的作者可能会允许他们解决问题。也许通过抑制该功能的提示。