İlk olarak, bu sorunun uzunluğu için özür dilerim.
Ben yazarı değilim IronScheme . Son zamanlarda 'yerli' .NET hata ayıklayıcıyı kullanabilmem için iyi hata ayıklama bilgileri yaymaya çalışıyorum.
Bu kısmen başarılı olsa da, bazı diş çıkarma sorunlarıyla karşılaşıyorum.
İlk sorun adımlama ile ilgilidir.
Şema'nın bir ifade dili olması nedeniyle, ifade (veya satır) tabanlı görünen büyük .NET dillerinin aksine, her şey parantez içine alınma eğilimindedir.
Orijinal kod (Şema) şöyle görünür:
(define (baz x)
(cond
[(null? x)
x]
[(pair? x)
(car x)]
[else
(assertion-violation #f "nooo" x)]))
Her ifadeyi bir satırsonuna koymuştum.
Yayılan kod C # 'e (ILSpy aracılığıyla) dönüşür:
public static object ::baz(object x)
{
if (x == null)
{
return x;
}
if (x is Cons)
{
return Builtins.Car(x);
}
return #.ironscheme.exceptions::assertion-violation+(
RuntimeHelpers.False, "nooo", Builtins.List(x));
}
Gördüğünüz gibi oldukça basit.
Not: Kod C # 'da koşullu ifadeye (? :) dönüştürülmüşse, her şey bir hata ayıklama adımı olacaktır, bunu aklınızda bulundurun.
Kaynak ve satır numaraları ile IL çıkışı:
.method public static object '::baz'(object x) cil managed
{
// Code size 56 (0x38)
.maxstack 6
.line 15,15 : 1,2 ''
//000014:
//000015: (define (baz x)
IL_0000: nop
.line 17,17 : 6,15 ''
//000016: (cond
//000017: [(null? x)
IL_0001: ldarg.0
IL_0002: brtrue IL_0009
.line 18,18 : 7,8 ''
//000018: x]
IL_0007: ldarg.0
IL_0008: ret
.line 19,19 : 6,15 ''
//000019: [(pair? x)
.line 19,19 : 6,15 ''
IL_0009: ldarg.0
IL_000a: isinst [IronScheme]IronScheme.Runtime.Cons
IL_000f: ldnull
IL_0010: cgt.un
IL_0012: brfalse IL_0020
IL_0017: ldarg.0
.line 20,20 : 7,14 ''
//000020: (car x)]
IL_0018: tail.
IL_001a: call object [IronScheme]IronScheme.Runtime.Builtins::Car(object)
IL_001f: ret
IL_0020: ldsfld object
[Microsoft.Scripting]Microsoft.Scripting.RuntimeHelpers::False
IL_0025: ldstr "nooo"
IL_002a: ldarg.0
IL_002b: call object [IronScheme]IronScheme.Runtime.Builtins::List(object)
.line 22,22 : 7,40 ''
//000021: [else
//000022: (assertion-violation #f "nooo" x)]))
IL_0030: tail.
IL_0032: call object [ironscheme.boot]#::
'ironscheme.exceptions::assertion-violation+'(object,object,object)
IL_0037: ret
} // end of method 'eval-core(033)'::'::baz'
Not: Hata ayıklayıcının tüm yöntemi basitçe vurgulamasını önlemek için, yöntem giriş noktasını sadece 1 sütun genişliğinde yapıyorum.
Gördüğünüz gibi, her ifade doğru bir çizgiyle eşleşir.
Şimdi adımlama sorunu (VS2010'da test edildi, ancak VS2008'de aynı / benzer sorun):
Bunlar IgnoreSymbolStoreSequencePoints
uygulanmamıştır.
- Null arg ile baz deyin, doğru çalışıyor. (null? x) ardından x.
- Baz işlevini Cons arg ile arayın, doğru çalışıyor. (null? x) sonra (çift? x) sonra (araba x).
- Baz'ı diğer arg ile arayın, başarısız olur. (null? x) sonra (çift? x) sonra (araba x) sonra (onaylama ihlali ...).
Başvururken IgnoreSymbolStoreSequencePoints
(önerildiği gibi):
- Null arg ile baz deyin, doğru çalışıyor. (null? x) ardından x.
- Eks arg ile baz deyin, başarısız olur. (null? x) sonra (pair? x).
- Baz'ı diğer arg ile arayın, başarısız olur. (null? x) sonra (çift? x) sonra (araba x) sonra (onaylama ihlali ...).
Ayrıca bu modda bazı satırların (burada gösterilmiyor) yanlış vurgulandığını, 1 ile kapandığını görüyorum.
İşte nedenlerin neler olabileceği hakkında bazı fikirler:
- Kuyruk çağrıları hata ayıklayıcıyı karıştırır
- Çakışan konumlar (burada gösterilmemiştir) hata ayıklayıcıyı karıştırır (kesme noktası ayarlarken çok iyi sonuç verir)
- ????
İkinci ama aynı zamanda ciddi olan sorun, hata ayıklayıcının bazı durumlarda kesme noktalarını kırmaması / vurmamasıdır.
Hata ayıklayıcının doğru (ve tutarlı bir şekilde) kırılmasını sağlayabildiğim tek yer yöntem giriş noktasındadır.
IgnoreSymbolStoreSequencePoints
Uygulanmadığında durum biraz daha iyileşir .
Sonuç
VS hata ayıklayıcı sadece düz bir hata olabilir :(
Referanslar:
Güncelleme 1:
Mdbg 64 bit derlemelerde çalışmaz. Yani bu çıktı. Test etmek için artık 32-bit makinem yok. Güncelleme: Bunun büyük bir sorun olmadığından eminim, birinin düzeltmesi var mı? Düzenleme: Evet, aptal bana, sadece x64 komut istemi altında mdbg başlatın :)
Güncelleme 2:
Bir C # uygulaması oluşturdum ve satır bilgisini incelemeye çalıştım.
Bulgularım:
- Herhangi bir
brXXX
talimattan sonra bir sıralama noktasına sahip olmanız gerekir (geçerli değilse '#line gizli', a yayarsınıznop
). - Herhangi bir
brXXX
talimattan önce , '#line hidden' ve anop
.
Ancak bunu uygulamak, sorunları düzeltemez (yalnız mı?).
Ancak aşağıdakileri eklemek istediğiniz sonucu verir :)
- Sonra
ret
, '#line hidden' ve anop
.
Bu, IgnoreSymbolStoreSequencePoints
uygulanmayan modu kullanıyor . Uygulandığında, bazı adımlar atlanır :(
Yukarıda uygulandığında IL çıktısı:
.method public static object '::baz'(object x) cil managed
{
// Code size 63 (0x3f)
.maxstack 6
.line 15,15 : 1,2 ''
IL_0000: nop
.line 17,17 : 6,15 ''
IL_0001: ldarg.0
.line 16707566,16707566 : 0,0 ''
IL_0002: nop
IL_0003: brtrue IL_000c
.line 16707566,16707566 : 0,0 ''
IL_0008: nop
.line 18,18 : 7,8 ''
IL_0009: ldarg.0
IL_000a: ret
.line 16707566,16707566 : 0,0 ''
IL_000b: nop
.line 19,19 : 6,15 ''
.line 19,19 : 6,15 ''
IL_000c: ldarg.0
IL_000d: isinst [IronScheme]IronScheme.Runtime.Cons
IL_0012: ldnull
IL_0013: cgt.un
.line 16707566,16707566 : 0,0 ''
IL_0015: nop
IL_0016: brfalse IL_0026
.line 16707566,16707566 : 0,0 ''
IL_001b: nop
IL_001c: ldarg.0
.line 20,20 : 7,14 ''
IL_001d: tail.
IL_001f: call object [IronScheme]IronScheme.Runtime.Builtins::Car(object)
IL_0024: ret
.line 16707566,16707566 : 0,0 ''
IL_0025: nop
IL_0026: ldsfld object
[Microsoft.Scripting]Microsoft.Scripting.RuntimeHelpers::False
IL_002b: ldstr "nooo"
IL_0030: ldarg.0
IL_0031: call object [IronScheme]IronScheme.Runtime.Builtins::List(object)
.line 22,22 : 7,40 ''
IL_0036: tail.
IL_0038: call object [ironscheme.boot]#::
'ironscheme.exceptions::assertion-violation+'(object,object,object)
IL_003d: ret
.line 16707566,16707566 : 0,0 ''
IL_003e: nop
} // end of method 'eval-core(033)'::'::baz'
Güncelleme 3:
Yukarıdaki 'yarı düzeltme' ile ilgili sorun. Peverify, nop
sonrası nedeniyle tüm yöntemlerle ilgili hataları bildirir ret
. Sorunu gerçekten anlamıyorum. Nasıl bir nop
mola doğrulamasından sonra a ret
. Ölü kod gibidir (kod bile DEĞİLDİR hariç) ... Oh, deneyler devam ediyor.
Güncelleme 4:
Şimdi evde, VS2008 üzerinde çalışan 'doğrulanamayan' kod kaldırıldı ve işler çok daha kötü. Belki de uygun hata ayıklama uğruna doğrulanamayan kod çalıştırmak cevap olabilir. 'Serbest bırakma' modunda, tüm çıktılar hala doğrulanabilir.
Güncelleme 5:
Şimdi yukarıdaki fikrimin tek uygun seçenek olduğuna karar verdim. Oluşturulan kod doğrulanamaz olsa da, henüz herhangi bir bulmak VerificationException
's. Bu senaryo ile son kullanıcı üzerindeki etkisinin ne olacağını bilmiyorum.
Bonus olarak, ikinci sayım da çözüldü. :)
İşte sonunda ne ile ilgili biraz screencast . Kesme noktalarına çarpar, uygun adım (giriş / çıkış / üst) vb. Yapar. Sonuç olarak, istenen etki.
Bununla birlikte, bunu hala bunu yapmanın yolu olarak kabul etmiyorum. Bana çok acayip geliyor. Gerçek konuda bir onay olması güzel olurdu.
Güncelleme 6:
VS2010'da kodu test etmek için değişiklik yaptım, bazı problemler var gibi görünüyor:
İlk çağrı artık doğru adım atmıyor. (iddia ihlali ...) vuruldu. Diğer durumlarda iyi çalışıyor.Bazı eski kodlar gereksiz pozisyonlar çıkarmıştır. Kod kaldırıldı, beklendiği gibi çalışıyor. :)- Daha ciddi olarak, kesme noktaları programın ikinci çağrısında başarısız olur (bellek içi derleme kullanarak, dosyaya damping montajı kesme noktalarını tekrar mutlu ediyor gibi görünüyor).
Bu iki durum da VS2008 altında düzgün çalışır. Temel fark VS2010 altında, tüm uygulamanın .NET 4 için derlenmiş olması ve VS2008 altında .NET 2 için derlenmesidir.
Güncelleme 7:
Belirtildiği gibi, 64 bit altında mdbg çalıştıran var. Ne yazık ki, programı yeniden çalıştırırsam kırılamayan kesme noktası sorunu da var (bu yeniden derlendiğini gösteriyor, bu yüzden aynı montajı değil, aynı kaynağı kullanıyor).
Güncelleme 8:
Ben var bir hata açtı kesme noktası konuyla ilgili MS Bağlan sitesinde.
Güncelleme: Sabit
Güncelleme 9:
Uzun bir düşünmeden sonra, hata ayıklayıcıyı mutlu etmenin tek yolu SSA yapmak gibi görünüyor, bu nedenle her adım izole edilebilir ve sıralanabilir. Yine de bu fikri kanıtlayamadım. Ama mantıklı görünüyor. Açıkçası, SSA'dan temper temizliği hata ayıklamayı kıracaktır, ancak bu geçiş yapmak kolaydır ve onları bırakmak çok fazla yüke sahip değildir.
nop
s olmadan, adım başarısız olur (emin olmak için bunu tekrar doğrulayacağım). Sanırım yapmak zorunda olduğum bir fedakarlık. VS'nin yönetici hakları olmadan bile çalışabileceği gibi değil :) Reflection kullanarak BTW.