.NET 4 x86 titreşiminde bir kod oluşturma hatası buldunuz. Çok alışılmadık bir durum, sadece kod optimize edilmediğinde başarısız oluyor. Makine kodu şuna benzer:
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
Optimize edilmemiş kod için normal olan çok sayıda geçici ve kod çoğaltma içeren bir plodding ilişkisi. 013F04B8'deki talimat dikkat çekicidir, yani sbyte'den 32 bitlik bir tam sayıya gerekli dönüşüm gerçekleşir. Dizi alıcısı yardımcı işlevi, State.BUG'a eşit olan 0x0000000FF döndürdü ve değer karşılaştırılmadan önce -1'e (0xFFFFFFFF) dönüştürülmesi gerekiyor. MOVSX komutu bir Sign eXtension talimatıdır.
Aynı şey tekrar 013F04CC'de olur, ancak bu sefer hiçbir şey yok aynı dönüşümü yapacak MOVSX komutu . Çiplerin düştüğü yer, CMP komutu 0xFFFFFFFF ile 0x000000FF'yi karşılaştırır ve bu yanlıştır. Bu bir ihmal hatasıdır, kod üreteci aynı sbyte int dönüşümü gerçekleştirmek için MOVSX'i tekrar yayamadı.
Bu hata hakkında özellikle sıra dışı olan şey, optimize ediciyi etkinleştirdiğinizde bunun doğru çalışmasıdır, şimdi her iki durumda da MOVSX'i kullanmayı biliyor.
Bu hatanın bu kadar uzun süre fark edilmemesinin olası nedeni, sümenin enumun temel türü olarak kullanılmasıdır. Yapmak oldukça nadir. Çok boyutlu bir dizi kullanmak da yararlıdır, kombinasyon ölümcüldür.
Aksi takdirde oldukça kritik bir hata diyebilirim. Ne kadar yaygın olabileceğini tahmin etmek zor, test etmek için sadece 4.6.1 x86 titreşim var. X64 ve 3.5 x86 titreşimi çok farklı kodlar oluşturur ve bu hatayı önler. Devam etmek için geçici geçici çözüm, enum base türü olarak sbyte'yi kaldırmak ve varsayılan, int , bu nedenle herhangi bir işaret uzantısı gerekmez.
Connect.microsoft.com adresindeki hatayı dosyalayabilirsiniz, bu Q + A'ya bağlantı vermek bilmeleri gereken her şeyi anlatmak için yeterli olmalıdır. Zaman ayırmak istemiyorsanız bana bildirin, ben de ilgilenirim.