Có lỗi trong Delphi 2006 nếu kích hoạt kiểm tra tràn và tối ưu hóa. Lỗi này dường như chỉ xuất hiện trong tình huống cụ thể trong đó một số nguyên 32 bit được thêm vào chính nó, và sau đó một byte được thêm vào tổng số trước đó, theo thứ tự cụ thể này, như được thấy trên chương trình bên dưới.Lỗi tối ưu hóa Delphi 2006
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.
Lưu ý: Kiểm tra tràn phải được mã hóa trong tệp nguồn chứ không phải qua tùy chọn dự án. Điều này dẫn chúng ta đến một lỗi khác: Phát hiện tràn qua các tùy chọn dự án không có hiệu lực.
Như đã thấy trên cửa sổ CPU, tôi ưu hoa bị phân tâm bởi một động thái với zero mở rộng movzx (mở rộng một giá trị 8-bit đến một giá trị 32 bit) và bởi việc kiểm tra tràn, quên để tải byte b trên một thanh ghi riêng biệt, ghi đè các nội dung trước đó, với hiệu ứng ròng của việc thêm b vào chính nó thay vì 2i. Nửa trên của mã lắp ráp dưới đây thuộc về chức năng bị lỗi trong khi nửa dưới của cấu trúc lành mạnh.
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
Nhân tiện, mã này không phải là một ví dụ bệnh lý, tôi tìm thấy nó trong khi điều chỉnh chương trình TeX tuyệt vời của D.Knuth thành Pascal hiện đại. Khi kiểm tra hiệu quả của việc bật tối ưu hóa và tắt tất cả các kiểm tra trình biên dịch trên kích thước * .exe cuối cùng, nó không thể diễn giải các bảng băm được lưu lại một cách chính xác (được tạo ra với tối ưu hóa bị tắt), mà tôi truy tìm lại ở trên lỗi, là phần tạo ra các bảng.
Câu hỏi rất đơn giản, ai đó có thể kiểm tra chương trình trên phiên bản mới hơn của Delphi?
Tôi đã thử nghiệm ở XE4 và kết quả giống nhau: 2 và sau đó 1 – Graymatter
Cảm ơn bạn đã kiểm tra, Gray. –
tôi đã thử nghiệm trong XE3 và kết quả là như nhau 2 và sau đó 1. nhưng nếu tôi chuyển sang 64-bit, nó sẽ in kết quả chính xác. –