सबसे पहले, मैं इस प्रश्न की लंबाई के लिए माफी माँगता हूँ।
मैं आयरनस्चेम का लेखक हूं । हाल ही में मैं सभ्य डिबग जानकारी का उत्सर्जन करने के लिए कड़ी मेहनत कर रहा हूं, ताकि मैं 'मूल' .NET डीबगर का उपयोग कर सकूं।
हालांकि यह आंशिक रूप से सफल रहा है, मैं कुछ शुरुआती समस्याओं में भाग रहा हूं।
पहली समस्या कदम से संबंधित है।
योजना एक अभिव्यक्ति की भाषा होने के कारण, सब कुछ मुख्य .NET भाषाओं के विपरीत, कोष्ठक में लिपटे रहने की प्रवृत्ति है, जो कि कथन (या पंक्ति) पर आधारित लगता है।
मूल कोड (योजना) इस प्रकार है:
(define (baz x)
(cond
[(null? x)
x]
[(pair? x)
(car x)]
[else
(assertion-violation #f "nooo" x)]))
मैं उद्देश्य पर एक नई लाइन पर प्रत्येक अभिव्यक्ति रखी है।
उत्सर्जित कोड C (# ILSpy के माध्यम से) रूपांतरित होता है:
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));
}
जैसा कि आप देख सकते हैं, बहुत आसान है।
नोट: यदि कोड एक सशर्त अभिव्यक्ति में बदल गया था (? :) C C में, तो पूरी बात सिर्फ एक डिबग कदम होगी, इसे ध्यान में रखें।
यहाँ स्रोत और लाइन नंबरों के साथ IL आउटपुट है:
.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'
नोट: डीबगर को पूरी विधि को केवल हाइलाइट करने से रोकने के लिए, मैं विधि प्रविष्टि बिंदु को सिर्फ 1 कॉलम चौड़ा बनाता हूं।
जैसा कि आप देख सकते हैं, प्रत्येक अभिव्यक्ति एक पंक्ति में सही ढंग से मैप करती है।
अब कदम के साथ समस्या (VS2010 पर परीक्षण किया गया, लेकिन VS2008 पर समान / समान मुद्दा):
ये IgnoreSymbolStoreSequencePoints
लागू नहीं हैं।
- नल आर्ग के साथ बाज को कॉल करें, यह सही ढंग से काम करता है। (null? x) x के बाद।
- विपक्ष के साथ कॉल बाज, यह सही ढंग से काम करता है। (नल? x) तब (जोड़ी? x) तब (कार x)।
- अन्य आर्ग के साथ बाज को कॉल करें, यह विफल रहता है। (null? x) तब (जोड़ी? x) तब (कार x) फिर (जोर-उल्लंघन ...)।
आवेदन करते समय IgnoreSymbolStoreSequencePoints
(अनुशंसित के रूप में):
- नल आर्ग के साथ बाज को कॉल करें, यह सही ढंग से काम करता है। (null? x) x के बाद।
- विपक्ष के साथ कॉल बाज, यह विफल रहता है। (नल? x) तब (जोड़ी? x)।
- अन्य आर्ग के साथ बाज को कॉल करें, यह विफल रहता है। (null? x) तब (जोड़ी? x) तब (कार x) फिर (जोर-उल्लंघन ...)।
मुझे इस विधा में भी पता चलता है कि कुछ लाइनें (यहां नहीं दिखाई गई हैं) गलत तरीके से हाइलाइट की गई हैं, वे 1 से बंद हैं।
यहाँ कुछ विचार दिए गए हैं कि क्या कारण हो सकते हैं:
- Tailcalls डिबगर को भ्रमित करता है
- ओवरलैपिंग स्थानों (यहाँ नहीं दिखाया गया है) डिबगर को भ्रमित करता है (ब्रेकपॉइंट सेट करते समय यह बहुत अच्छा करता है)
- ????
दूसरा, लेकिन गंभीर भी है, समस्या कुछ मामलों में ब्रेकपॉइंट को तोड़ने / हिट करने में विफल डिबगर है।
एकमात्र स्थान जहां मैं डिबगर को सही तरीके से (और लगातार) तोड़ने के लिए प्राप्त कर सकता हूं, विधि प्रविष्टि बिंदु पर है।
IgnoreSymbolStoreSequencePoints
लागू नहीं होने पर स्थिति थोड़ी बेहतर हो जाती है।
निष्कर्ष
यह हो सकता है कि वी.एस. डीबगर सिर्फ सादा छोटी गाड़ी है :(
संदर्भ:
अपडेट 1:
Mdbg 64-बिट असेंबलियों के लिए काम नहीं करता है। तो वह बाहर है। मेरे पास इस पर परीक्षण करने के लिए और अधिक 32-बिट मशीनें नहीं हैं। अद्यतन: मुझे यकीन है कि यह कोई बड़ी समस्या नहीं है, क्या किसी को भी ठीक करना है? संपादित करें: हाँ, मुझे मूर्ख, बस x64 कमांड प्रॉम्प्ट के तहत mdbg शुरू करें :)
अपडेट 2:
मैंने एक C # ऐप बनाया है, और लाइन की जानकारी को अलग करने की कोशिश की है।
मेरे निष्कर्ष:
- किसी भी
brXXX
निर्देश के बाद आपको एक अनुक्रम बिंदु (यदि मान्य aka '#line छिपा हुआ नहीं है, तो उत्सर्जन करेंnop
)' की आवश्यकता है। - किसी भी
brXXX
निर्देश से पहले , एक '# छिपी हुई' और ए का उत्सर्जन करेंnop
।
इसे लागू करना, हालांकि मुद्दों (अकेले?) को ठीक नहीं करता है।
लेकिन निम्नलिखित को जोड़ने से वांछित परिणाम मिलता है :)
- बाद में
ret
, '# छिपी हुई' और ए का उत्सर्जन करेंnop
।
यह उस मोड का उपयोग कर रहा है जहां IgnoreSymbolStoreSequencePoints
लागू नहीं है। जब लागू किया जाता है, तो कुछ कदम अभी भी छोड़ दिए जाते हैं :(
यहाँ IL आउटपुट है जब ऊपर लागू किया गया है:
.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'
अपडेट 3:
ऊपर 'सेमी-फिक्स' के साथ समस्या। nop
बाद के कारण सभी तरीकों पर रिपोर्टों की त्रुटियों का लाभ उठाएं ret
। मैं वास्तव में समस्या को नहीं समझता। एक के nop
बाद एक ब्रेक सत्यापन कैसे हो सकता है ret
। यह मृत कोड की तरह है (सिवाय इसके कि यह कोड भी नहीं है) ... ओह ठीक है, प्रयोग जारी है।
अपडेट 4:
घर पर वापस, अब 'अपरिवर्तनीय' कोड को हटा दिया, VS2008 पर चल रहा है और चीजें बहुत खराब हैं। शायद उचित डिबगिंग के लिए अपरिवर्तनीय कोड चलाना उत्तर हो सकता है। 'रिलीज़' मोड में, सभी आउटपुट अभी भी सत्यापन योग्य होंगे।
अपडेट 5:
मैंने अब निर्णय लिया है कि मेरा उपरोक्त विचार अब के लिए एकमात्र व्यवहार्य विकल्प है। यद्यपि उत्पन्न कोड अपरिवर्तनीय है, मुझे अभी तक कोई भी पता नहीं है VerificationException
। मुझे नहीं पता कि इस परिदृश्य के साथ अंतिम उपयोगकर्ता पर क्या प्रभाव पड़ेगा।
एक बोनस के रूप में, मेरा दूसरा मुद्दा भी हल हो गया है। :)
यहाँ मैं क्या साथ समाप्त की एक छोटी सी पेंच है। यह ब्रेकपॉइंट्स को हिट करता है, उचित स्टेपिंग (इन / आउट / ओवर), आदि सभी में, वांछित प्रभाव।
हालाँकि, मैं अभी भी इसे करने के तरीके के रूप में स्वीकार नहीं कर रहा हूँ। यह मुझ पर भारी लग रहा है। असली मुद्दे पर पुष्टि होने के बाद अच्छा होगा।
अद्यतन 6:
बस VS2010 पर कोड का परीक्षण करने के लिए परिवर्तन किया गया था, कुछ समस्याएं हैं:
पहला कॉल अब सही तरीके से नहीं होता है। (जोर-आजमाइश ...) हिट है। अन्य मामले ठीक काम करते हैं।कुछ पुराने कोड अनावश्यक पदों का उत्सर्जन करते हैं। कोड को हटा दिया, उम्मीद के मुताबिक काम करता है। :)- अधिक गंभीरता से, ब्रेकपॉइंट प्रोग्राम के दूसरे आह्वान पर विफल होते हैं (इन-मेमोरी संकलन का उपयोग करते हुए, फाइल को असेंबली डंप करना ब्रेकपॉइंट को फिर से खुश करने के लिए लगता है)।
ये दोनों मामले VS2008 के तहत सही तरीके से काम करते हैं। मुख्य अंतर यह है कि VS2010 के तहत, संपूर्ण अनुप्रयोग .NET 4 के लिए और VS2008 के तहत, .NET 2 के लिए संकलित है। दोनों 64-बिट चल रहे हैं।
अपडेट 7:
उल्लेख के अनुसार, मैं 64-बिट के तहत mdbg चला रहा हूं। दुर्भाग्य से, इसका ब्रेकपॉइंट मुद्दा भी है जहां यह टूटने में विफल रहता है अगर मैं कार्यक्रम को फिर से चलाता हूं (इसका मतलब है कि यह फिर से व्यवस्थित हो जाता है, इसलिए एक ही विधानसभा का उपयोग नहीं कर रहा है, लेकिन अभी भी उसी स्रोत का उपयोग कर रहा है)।
अपडेट 8:
मैंने ब्रेक कनेक्ट मुद्दे के बारे में एमएस कनेक्ट साइट पर एक बग दर्ज किया है।
अपडेट: फिक्स्ड
अपडेट 9:
कुछ लंबी सोच के बाद, डिबगर को खुश करने का एकमात्र तरीका एसएसए कर रहा है, इसलिए हर कदम को अलग और अनुक्रमिक किया जा सकता है। मैं हालांकि इस धारणा को साबित नहीं कर पा रहा हूं। लेकिन यह तर्कसंगत लगता है। जाहिर है, एसएसए से टेम्पों की सफाई डिबगिंग को तोड़ देगी, लेकिन यह आसान है टॉगल करना, और उन्हें छोड़ना बहुत अधिक उपरि नहीं है।
nop
, चरणबद्धता विफल हो जाती है (मैं यह सुनिश्चित करने के लिए फिर से सत्यापित करूंगा)। यह एक ऐसा बलिदान है जो मुझे लगता है कि मुझे बनाना होगा। यह ऐसा नहीं है कि वीएस बिना प्रशासक अधिकारों के भी चल सकता है :) रिफ्लेक्शन का उपयोग करके Btw। DLR के माध्यम से स्वीकार करें (एक बहुत जल्दी हैक की गई शाखा)।