2017-01-18 3 views
1

Код указан ниже от DDetours.pas. Когда он компилируется для 32 бит, никаких предупреждений не возникает. Когда он компилирует для 64-битных, он излучает это предупреждение: (Delphi Berlin Update 2)Почему dcc64 говорит, что это значение никогда не используется?

[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, когда используется начальное значение.

ответ

1

Это ошибка компилятора. Есть несколько подобных. Довольно неприятно. Иногда 32-битный компилятор будет жаловаться иррациональным образом, а затем, когда вы обходитесь с тем, что 64-битный компилятор в свою очередь жалуется иррациональным образом на ваш обходной путь.

Я не думаю, что Embarcadero обычно использует компилятор с подсказками и предупреждениями, потому что их библиотечный код полон подсказок и предупреждений.

В любом случае, в этом случае компилятор видит, что две записи относятся к переменной, но по какой-то причине не распознают промежуточное чтение переменной.

Существует не так много, что вы можете сделать. Вы можете отправить отчет об ошибке. Я ожидаю, что вы не захотите изменить код, потому что это сторонний код. Если вы не измените его, вам придется мириться с фиктивным намеком.

Уведомление об авторе библиотеки может позволить им решить проблему. Возможно, подавляя намеки на эту функцию.

+1

Мое решение состоит в том, чтобы добавить это в начало устройства: {$ IFDEF WIN64} {$ HINTS OFF} // dcc64 дает недопустимые подсказки в этом устройстве. {$ ENDIF} –

+0

@DavidHeffernan «Я не думаю, что Embarcadero обычно использует компилятор с подсказками и предупреждениями, потому что их библиотечный код полон подсказок и предупреждений». Вы перекомпилируете 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: То же самое. В этом случае компилятор может знать во время компиляции, что цикл никогда не будет вводиться во время выполнения, поскольку первая оценка всегда будет ложной, но она все равно должна генерировать код для инициализации переменной, и поэтому она может предупреждать, зная, что назначение будет не использовано. –

+0

@DavidHeffernan: если вы не находитесь в команде компилятора, вы не знаете, что он на самом деле делает. Я размышляю, так и есть. Но я не вижу, чтобы было сложно выполнить некоторый простой анализ потока, например, при компиляции кода оценки цикла. –

Смежные вопросы