SORU
30 Kasım 2012, Cuma


çift? = çift? çift?

StackOverflow topluluk veya C bu basit bit ile aklımı kaybediyorum olup olmadığını görmek için ping istedim# kodu.

Windows 7, bu bina üzerinde geliştiriyorum .NET 4.0, 64 hata Ayıklama.

Aşağıdaki kodu var:

static void Main()
{
    double? y = 1D;
    double? z = 2D;

    double? x;
    x = y   z;
}

Eğer ben ve brace kaşlı biten bir kesme hata ayıklama koyarsanız, = 3 Penceresi ve Komut Penceresi (x) bekliyorum. x = yerine boş.

Ben 86, işler pek iyi hata ayıklama. Bir şey x 64 derleyici ile yanlış ya da yolunda gitmeyen bir şeyler?

CEVAP
30 Kasım 2012, Cuma


'Yanıt JİT ölü kodu en iyi duruma getirme hakkında doğru ( . Douglas ^em>her ikisi dex 86 ve x 64 Derleyiciler bunu). Eğer JİT derleyici ölü kod optimize edildi ancak, x bile Yereller penceresinde görünmeyecek çünkü hemen belli olur. Ayrıca, izlemek ve acil pencere erişmeye çalışırken bir hata verecektir bunun yerine: "adı 'geçerli bağlamda yok". x Bunun gibi anlattığın şey değil.

Görmekte olduğunuz şey aslında Visual Studio 2010 bir hata değildir.

İlk olarak, benim ana makinede bu sorunu yeniden oluşturmaya çalıştım: Win7x64 ve VS2012. İçin .NET 4.0 hedefler, x kapatma küme ayracı üzerinde kırıldığında 3.0 D eşittir. Denemeye karar verdim .3.5 hedefler NET, ve o, x da 3.0 D ayarlandı, NOT null.

Aldığımdan beri bu sorun mükemmel bir sunumu yapamam beri .NET 4.5 üstüne kurulu .NET 4.0, ben sanal makine ve yüklü bir VS2010 döndü.

Burada, sorunu yeniden mümkün oldu. Her iki gözcü penceresi ve yereller penceresinde Main yöntemin kapatma küme ayracının bir kesme noktası ile, x null olduğunu gördüm. Bu ilginç bir hal almaya başlıyor. V2 hedef aldım.0 yerine çalışma zamanı ve boş oraya da bulundu. Elbette ki aynı sürümünü beri bu durumda olamaz .Başarıyla 3.0D değeri x gösterdi diğer bilgisayarımda NET 2.0 çalışma zamanı.

O zaman ne oluyor? Windbg içinde araştırma sonra, sorunu buldum:

VS2010 aslında atandıktan önce x değerini gösteriyor.

Bu yönerge işaretçisi geçmiş x = y z satırı olduğu gibi görünüyor, ne olmadığını biliyorum. Bu kendinizi yöntemi için birkaç satır kod ekleyerek test edebilirsiniz:

double? y = 1D;
double? z = 2D;

double? x;
x = y   z;

Console.WriteLine(); // Don't reference x here, still leave it as dead code

Son kıvırcık kesme noktası ayracı ile, yerli ve penceresi 3.0D eşit x gösterir. Eğer kod boyunca adım ancak eğer VS2010 kadar atanmış olarak x göstermiyor fark edeceksinizsonraConsole.WriteLine() ile adım attın.

Eğer bu hata şimdiye kadar Microsoft Bağlamak için ihbar edildiğini bilmiyorum ama, örnek olarak bu kod ile yapmak isteyebilirsiniz. Açıkça VS2012 ancak sabit oldu, eğer bunu düzeltmek için bir güncelleme olacak eğer orada ya da değil emin değilim.


Burada aslında TAM zamanında ve VS2010 da ne oluyor

Orijinal kodu, VS ne yaptığını ve bunun yanlış olduğunu neden görebilirsiniz. Ayrıca x değişken montaj en iyi duruma getirme etkin ile derlenecek işaretlediğiniz sürece) optimize almıyor görebilirsiniz.

İlk olarak, IL yerel değişken tanımları bakalım:

.locals init (
    [0] valuetype [mscorlib]System.Nullable`1<float64> y,
    [1] valuetype [mscorlib]System.Nullable`1<float64> z,
    [2] valuetype [mscorlib]System.Nullable`1<float64> x,
    [3] valuetype [mscorlib]System.Nullable`1<float64> CS$0$0000,
    [4] valuetype [mscorlib]System.Nullable`1<float64> CS$0$0001,
    [5] valuetype [mscorlib]System.Nullable`1<float64> CS$0$0002)

Bu hata ayıklama modunda normal çıktı. Visual Studio atamaları sırasında kullandığı ve CS* değişken kopyalamak için ekstra IL komutları ilgili kullanıcı tanımlı ekler yerel değişkenler yinelenen yerel değişken tanımlar. İşte bu gerçek gösterir ilgili İL kodu:

// For the line x = y   z
L_0045: ldloca.s CS$0$0000 // earlier, y was stloc.3 (CS$0$0000)
L_0047: call instance !0 [mscorlib]System.Nullable`1<float64>::GetValueOrDefault()
L_004c: conv.r8            // Convert to a double
L_004d: ldloca.s CS$0$0001 // earlier, z was stloc.s CS$0$0001
L_004f: call instance !0 [mscorlib]System.Nullable`1<float64>::GetValueOrDefault()
L_0054: conv.r8            // Convert to a double 
L_0055: add                // Add them together
L_0056: newobj instance void [mscorlib]System.Nullable`1<float64>::.ctor(!0) // Create a new nulable
L_005b: nop                // NOPs are placed in for debugging purposes
L_005c: stloc.2            // Save the newly created nullable into `x`
L_005d: ret 

Hadi biraz daha derine WinDbg ile hata ayıklama yapın:

Sen VS2010 uygulama ve hata ayıklama yöntemi sonunda bir kesme bırakırsanız, WinDbg kolay, non-invaziv modunda ekleyebilirsiniz.

İşte çağrı Main yöntemi için bir çerçeve oluşturuyor. IP (Yönerge işaretçisi) önemsiyoruz.

0:009> !clrstack
OS Thread Id: 0x135c (9)
Child SP         IP               Call Site
000000001c48dc00 000007ff0017338d ConsoleApplication1.Program.Main(System.String[])
[And so on...]

Eğer Main yöntemi için yerel makine kodu kabul edersek, talimatlar VS yürütme tatili anda çalıştırmak ne görebiliriz:

000007ff`00173388 e813fe25f2      call    mscorlib_ni 0xd431a0 
           (000007fe`f23d31a0) (System.Nullable`1[[System.Double, mscorlib]]..ctor(Double), mdToken: 0000000006001ef2)
****000007ff`0017338d cc              int     3****
000007ff`0017338e 8d8c2490000000  lea     ecx,[rsp 90h]
000007ff`00173395 488b01          mov     rax,qword ptr [rcx]
000007ff`00173398 4889842480000000 mov     qword ptr [rsp 80h],rax
000007ff`001733a0 488b4108        mov     rax,qword ptr [rcx 8]
000007ff`001733a4 4889842488000000 mov     qword ptr [rsp 88h],rax
000007ff`001733ac 488d8c2480000000 lea     rcx,[rsp 80h]
000007ff`001733b4 488b01          mov     rax,qword ptr [rcx]
000007ff`001733b7 4889442440      mov     qword ptr [rsp 40h],rax
000007ff`001733bc 488b4108        mov     rax,qword ptr [rcx 8]
000007ff`001733c0 4889442448      mov     qword ptr [rsp 48h],rax
000007ff`001733c5 eb00            jmp     000007ff`001733c7
000007ff`001733c7 0f28b424c0000000 movaps  xmm6,xmmword ptr [rsp 0C0h]
000007ff`001733cf 4881c4d8000000  add     rsp,0D8h
000007ff`001733d6 c3              ret

Main, !clrstack var olan geçerli IP kullanarak yürütme talimat üzerine askıya alınmıştı bakındoğrudan sonraSystem.Nullable<double>çağrısı'nin kurucu. (int 3 kesme hata ile yürütme durdurmak için kullanılır) *ile's, ve ayrıca, IL L_0056 satır maç. çevrili.

Aslında izleyen 64 Meclisi yerel değişken x atar. Talimat bizim işaretçi henüz kod idam etmedi, VS2010 zamanından önce x değişken yerel kod tarafından atanmış önce kırılıyor.

EDİT: 64 int 3 yukarıdaki talimatları. gördüğünüz gibi atama kodundan önce yerleştirilir, Talimat atama kodundan sonra yerleştirilen 86,. O VS x 64 erken sadece kırılıyor açıklıyor. Zor bu Visual Studio hatası veya JİT derleyici olduğunu düşünüyor. Ekler kesme kanca hangi emin değilim.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • EEVblog2

    EEVblog2

    2 HAZİRAN 2014
  • LimeFire

    LimeFire

    2 ŞUBAT 2012
  • Manuel Vizcaino

    Manuel Vizca

    27 Mayıs 2008