В Delphi 2006 есть ошибка, если активировать проверку и оптимизацию переполнения. Кажется, что ошибка появляется только в конкретной ситуации, когда 32-битное целое добавляется к себе, а затем байт добавляется к этой предыдущей сумме в этом конкретном порядке, как показано ниже в программе.
program OptimizationBug;
{$OPTIMIZATION ON}
{$APPTYPE CONSOLE}
{$OVERFLOWCHECKS ON}
function f: integer;
var i: integer;
b: byte;
begin
i:=0;
b:=1;
Result:=i+i+b;
end;
{$OVERFLOWCHECKS OFF}
function g: integer;
var i: integer;
b: byte;
begin
i:=0;
b:=1;
Result:=i+i+b;
end;
begin
writeLn(f); //wrong, prints "2" in D2006
writeLn(g); //good, prints "1"
readLn;
end.
Примечание. Проверка переполнения должна быть закодирована в исходном файле, а не через параметры проекта. Это приводит нас к еще одной ошибке: обнаружение переполнения через параметры проекта не влияет.
Как видно на окне CPU, оптимизатор отвлекается на перемещение с нулевым расширением movzx (расширяя 8-битное значение до 32-битного значения) и проверкой переполнения, забывая загрузить байт b в отдельный регистр, перезаписывая предыдущее содержание, с чистым эффектом добавления b к себе вместо 2i. Верхняя половина ниже кода сборки относится к прослушанной функции, а нижняя - к строковой конструкции.
OptimizationBug.dpr.20: i:=0;
00403EAC 33C0 xor eax,eax
OptimizationBug.dpr.21: b:=1;
00403EAE B201 mov dl,$01
OptimizationBug.dpr.22: Result:=i+i+b;
00403EB0 03C0 add eax,eax
00403EB2 7105 jno $00403eb9
00403EB4 E82BF5FFFF call @IntOver
00403EB9 0FB6C2 movzx eax,dl //BUG: should have x-moved DL to EDX register!
00403EBC 03C0 add eax,eax // (and added EDX to EAX)
00403EBE 7105 jno $00403ec5
00403EC0 E81FF5FFFF call @IntOver
OptimizationBug.dpr.23: end;
00403EC5 C3 ret
00403EC6 8BC0 mov eax,eax
OptimizationBug.dpr.30: i:=0;
00403EC8 33C0 xor eax,eax
OptimizationBug.dpr.31: b:=1;
00403ECA B201 mov dl,$01
OptimizationBug.dpr.32: Result:=i+i+b;
00403ECC 03C0 add eax,eax
00403ECE 0FB6D2 movzx edx,dl //OK!
00403ED1 03C2 add eax,edx //ok
OptimizationBug.dpr.33: end;
00403ED3 C3 ret
Кстати, этот код не является патологическим примером, я нашел его, адаптируя великолепную программу TeX от D.Knuth к современному Паскалю. При проверке эффекта включения оптимизации и отключения всех проверок компилятора на окончательный размер *.exe он не смог правильно интерпретировать сохраненные хэш-таблицы диска (которые были сгенерированы с отключенной оптимизацией), которые я проследил до над ошибкой, которая является частью, которая генерирует таблицы.
Вопрос прост, может ли кто-нибудь проверить программу на более новой версии Delphi?