Mempertimbangkan:
using System;
public class Test
{
enum State : sbyte { OK = 0, BUG = -1 }
static void Main(string[] args)
{
var s = new State[1, 1];
s[0, 0] = State.BUG;
State a = s[0, 0];
Console.WriteLine(a == s[0, 0]); // False
}
}
Bagaimana ini bisa dijelaskan? Itu terjadi di debug membangun di Visual Studio 2015 ketika berjalan di x86 JIT. Rilis build atau running di x64 JIT mencetak True seperti yang diharapkan.
Untuk mereproduksi dari baris perintah:
csc Test.cs /platform:x86 /debug
( /debug:pdbonly
, /debug:portable
dan /debug:full
juga mereproduksi.)
ildasm
dan kemudianilasm
"memperbaikinya" .../debug=IMPL
daun bendera itu rusak;/debug=OPT
"memperbaikinya".Jawaban:
Anda menemukan bug pembuatan kode di .NET 4 x86 jitter. Ini sangat luar biasa, hanya gagal ketika kode tidak dioptimalkan. Kode mesin terlihat seperti ini:
Perselingkuhan dengan banyak temporer dan duplikasi kode, itu normal untuk kode yang tidak dioptimalkan. Instruksi pada 013F04B8 terkenal, di situlah konversi yang diperlukan dari sbyte ke integer 32-bit terjadi. Fungsi pembantu pengambil array mengembalikan 0x0000000FF, sama dengan State.BUG, dan yang perlu dikonversi ke -1 (0xFFFFFFFF) sebelum nilainya dapat dibandingkan. Instruksi MOVSX adalah instruksi Sign eXtension.
Hal yang sama terjadi lagi di 013F04CC, tetapi kali ini tidak ada instruksi MOVSX untuk melakukan konversi yang sama. Di situlah chip jatuh, instruksi CMP membandingkan 0xFFFFFFFF dengan 0x000000FF dan itu salah. Jadi ini adalah kesalahan kelalaian, pembuat kode gagal memancarkan MOVSX lagi untuk melakukan konversi yang sama ke konversi int.
Apa yang sangat tidak biasa tentang bug ini adalah bahwa ini berfungsi dengan benar ketika Anda mengaktifkan optimizer, sekarang tahu untuk menggunakan MOVSX dalam kedua kasus.
Kemungkinan alasan bahwa bug ini tidak terdeteksi begitu lama adalah penggunaan sbyte sebagai tipe dasar dari enum. Cukup langka untuk dilakukan. Menggunakan array multi dimensi juga penting, kombinasi ini fatal.
Kalau tidak, bug yang cukup kritis akan saya katakan. Seberapa luas itu mungkin sulit ditebak, saya hanya memiliki jitter 4.6.1 x86 untuk diuji. Jitter x64 dan 3.5 x86 menghasilkan kode yang sangat berbeda dan menghindari bug ini. Solusi sementara untuk melanjutkan adalah menghapus sbyte sebagai tipe enum base dan membiarkannya menjadi default, int , jadi tidak perlu ekstensi tanda.
Anda dapat mengajukan bug di connect.microsoft.com, menautkan ke Q + A ini harus cukup untuk memberi tahu mereka segala yang perlu mereka ketahui. Beritahu saya jika Anda tidak ingin meluangkan waktu dan saya akan membereskannya.
sumber
byte
bukannyasbyte
harus baik-baik saja dan mungkin lebih baik jika kode asli digunakan dengan mengatakan ORM di mana Anda tidak ingin bendera Anda di database mengambil ruang ekstra.Mari kita pertimbangkan deklarasi OP:
Karena bug hanya terjadi ketika
BUG
negatif (dari -128 ke -1) dan State adalah enum dari byte yang ditandatangani, saya mulai menganggap bahwa ada masalah pemeran di suatu tempat.Jika Anda menjalankan ini:
itu akan menampilkan:
Untuk alasan yang saya abaikan (seperti yang sekarang)
s[0, 0]
dilemparkan ke byte sebelum evaluasi dan itulah mengapa klaim itua == s[0,0]
salah.sumber