2017-01-18 5 views
1

아래 코드는 DDetours.pas에서 가져온 것입니다. 32 비트 용으로 컴파일하면 경고가 표시되지 않습니다. 여기 dcc64가이 값이 사용되지 않는다고 말하는 이유는 무엇입니까?

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

그것은 확실히 처음으로 같은 Prf처럼 나에게 보이는

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; 

문제가되는 기능입니다 (델파이 베를린 업데이트 2)가 64 비트에 대한 컴파일 할 때이 경고를 방출 초기 값이 사용되는 $ 8000과 비교됩니다.

답변

1

이것은 컴파일러 버그입니다. 이 성질의 몇 가지가 있습니다. 상당히 실망 스럽다. 때로는 32 비트 컴파일러가 불합리한 방식으로 불평 할 것이고, 그런 다음 해결 방법을 사용할 때 64 비트 컴파일러가 해결 방법에 대해 불합리한 방식으로 불평 할 수 있습니다.

라이브러리 코드가 힌트와 경고로 가득차 있기 때문에, 힌트와 경고가있는 습관적으로 컴파일러가 사용 가능하다고 생각하지 않습니다.

어쨌든이 경우 컴파일러는 변수에 대한 두 번의 쓰기를보고 있지만 어떤 이유로 변수의 중간 읽기를 인식하지 못합니다.

할 수있는 일이별로 없습니다. 버그 보고서를 제출할 수 있습니다. 제 3 자 코드이기 때문에 코드를 변경하고 싶지 않을 것으로 예상됩니다. 당신이 그것을 변경하지 않으면 당신은 가짜 힌트를 참 아야 할 것입니다.

라이브러리 작성자에게 알리면 문제를 해결할 수 있습니다. 아마도 해당 기능에 대한 힌트를 표시하지 않을 수 있습니다.

+1

제 생각에 해결책을 장치 상단에 추가하십시오 : {$ IFDEF WIN64} {$ HINTS OFF} // dcc64는이 장치에서 잘못된 힌트를 제공합니다. {$ ENDIF} –

+0

@DavidHeffernan "라이브러리 코드가 힌트와 경고로 가득하기 때문에 힌트와 경고를 사용하여 습관적으로 컴파일러를 사용할 수 있다고 생각하지 않습니다." RTL/VCL/...을 다시 컴파일합니까? 아니면 그렇게 생각하니? –

+0

@StefanGlienke 몇 가지 결함을 해결하기 위해 소수의 VCL 유닛을 다시 컴파일합니다. 모두에 경고와 힌트가 있습니다. 변수를 포함하는 것은 선언되었지만 사용되지는 않았으며, 상징적으로 사용되지 않는 경고가 많이있었습니다. 나는 여전히 XE7에있다. 아마도 그들은 긴축했습니다. –

1

글쎄, 나는 메시지에 관해서 dcc64가 버그가 많은 컴파일러라고 생각한다. 문제의 라인을 주석 처리하면 "사용하지 않은 값"이 "초기화되지 않았을 수 있습니다." 같은 컴파일러.

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

그것은 결함이 dcc64 것을 너무 많이하지 않습니다. dcc32에도 비슷한 문제가 많이 있습니다. –

2

나는 내장이 변수가 초기화 및 루프가 입력 될 때까지 다시 접촉되지

  • 것을 인식 할 수 있도록 64 비트 컴파일러는 영리의 작은 금액을 가지고 의심 .
  • 루프 조건은 변수를 리터럴과 비교합니다.
  • 초기 값 0은 루프 조건을 충족하므로 런타임에 루프가 항상 한 번 이상 실행되어 효과적으로 repeat..until 루프처럼 작동합니다.

컴파일러는 여전히 초기화를위한 코드를 생성해야하지만 런타임에 루프에 들어가기 위해 초기 값이 필요하지 않다는 것을 알고 있기 때문에 초기 값이 사용되지 않을 것이라는 경고를 발행 할 수 있습니다.

변수를 초기화하지 않으면 컴파일러에서 비헤이비어가 정의되지 않았기 때문에 루프가 입력되는지 여부를 컴파일시 알 수 없으므로 컴파일러에서 초기화되지 않은 변수에 대한 다른 경고를 발행합니다.


분해보기, 당신은 루프를 최적화하여 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 
+0

초기화를 $ 8000으로 변경하면 루프가 입력되지 않으므로 힌트가 사라지기 때문에 저는 그렇게 생각하지 않습니다. –

+0

@BrandonStaggs : 똑같은. 이 경우 컴파일러는 첫 번째 평가가 항상 false가 되었기 때문에 런타임에 루프를 입력하지 않을 것임을 컴파일 타임에 알 수 있지만 여전히 변수의 초기화를위한 코드를 생성해야하므로 알 수 있습니다 할당이 사용되지 않을 것입니다. –

+0

@DavidHeffernan : 당신이 컴파일러 팀에 속해 있지 않다면, 그것이 실제로 무엇을하는지 모른다. 나는 추측하고있다, 너도 그래. 그러나 루프 평가 코드를 컴파일 할 때 이런 간단한 흐름 분석을 수행하는 것이 어렵지는 않습니다. –

관련 문제