Bạn đã tìm thấy một lỗi tạo mã trong jitter .NET 4 x86. Đó là một điều rất bất thường, nó chỉ thất bại khi mã không được tối ưu hóa. Mã máy trông như thế này:
State a = s[0, 0];
013F04A9 push 0 ; index 2 = 0
013F04AB mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04AE xor edx,edx ; index 1 = 0
013F04B0 call 013F0058 ; eax = s[0, 0]
013F04B5 mov dword ptr [ebp-4Ch],eax ; $temp1 = eax
013F04B8 movsx eax,byte ptr [ebp-4Ch] ; convert sbyte to int
013F04BC mov dword ptr [ebp-44h],eax ; a = s[0, 0]
Console.WriteLine(a == s[0, 0]); // False
013F04BF mov eax,dword ptr [ebp-44h] ; a
013F04C2 mov dword ptr [ebp-50h],eax ; $temp2 = a
013F04C5 push 0 ; index 2 = 0
013F04C7 mov ecx,dword ptr [ebp-40h] ; s[] reference
013F04CA xor edx,edx ; index 1 = 0
013F04CC call 013F0058 ; eax = s[0, 0]
013F04D1 mov dword ptr [ebp-54h],eax ; $temp3 = eax
; <=== Bug here!
013F04D4 mov eax,dword ptr [ebp-50h] ; a == s[0, 0]
013F04D7 cmp eax,dword ptr [ebp-54h]
013F04DA sete cl
013F04DD movzx ecx,cl
013F04E0 call 731C28F4
Một vấn đề khó khăn với rất nhiều thời gian và sao chép mã, đó là bình thường đối với mã không được tối ưu hóa. Hướng dẫn tại 013F04B8 là đáng chú ý, đó là nơi xảy ra sự chuyển đổi cần thiết từ sbyte sang số nguyên 32 bit. Hàm trợ giúp mảng getter trả về 0x0000000FF, bằng State.BUG và cần được chuyển đổi thành -1 (0xFFFFFFFF) trước khi có thể so sánh giá trị. Lệnh MOVSX là một lệnh Sign eXtension.
Điều tương tự lại xảy ra một lần nữa tại 013F04CC, nhưng lần này không có hướng dẫn MOVSX để thực hiện chuyển đổi tương tự. Đó là nơi các chip rơi xuống, hướng dẫn CMP so sánh 0xFFFFFFFF với 0x000000FF và đó là sai. Vì vậy, đây là một lỗi thiếu sót, trình tạo mã không thể phát lại MOVSX để thực hiện cùng một sbyte để chuyển đổi int.
Điều đặc biệt khác thường về lỗi này là lỗi này hoạt động chính xác khi bạn kích hoạt trình tối ưu hóa, giờ đây nó đã biết sử dụng MOVSX trong cả hai trường hợp.
Lý do có thể xảy ra là lỗi này không bị phát hiện quá lâu là việc sử dụng sbyte làm loại cơ sở của enum. Khá hiếm để làm. Sử dụng một mảng đa chiều cũng là công cụ, sự kết hợp gây tử vong.
Nếu không, một lỗi khá nghiêm trọng tôi muốn nói. Làm thế nào rộng rãi có thể khó đoán, tôi chỉ có jitter 4.6.1 x86 để kiểm tra. Các jitter x64 và 3,5 x86 tạo mã rất khác nhau và tránh lỗi này. Cách giải quyết tạm thời để tiếp tục là loại bỏ sbyte làm loại cơ sở enum và để nó là mặc định, int , do đó không cần mở rộng dấu hiệu.
Bạn có thể gửi lỗi tại connect.microsoft.com, liên kết đến Q + A này là đủ để nói với họ mọi thứ họ cần biết. Hãy cho tôi biết nếu bạn không muốn dành thời gian và tôi sẽ chăm sóc nó.