आप द्विआधारी प्रारूप को कैसे डीबग करते हैं?


11

मैं बाइनरी बिल्डर के निर्माण में डिबग करने में सक्षम होना चाहूंगा। अभी मैं मूल रूप से बाइनरी पार्सर को इनपुट डेटा प्रिंट कर रहा हूं, और फिर कोड में गहराई से जा रहा हूं और इनपुट की मैपिंग को आउटपुट तक प्रिंट कर रहा हूं, फिर आउटपुट मैपिंग (पूर्णांक) ले रहा हूं और इसी पूर्णांक का पता लगाने के लिए उपयोग कर रहा हूं। बाइनरी में। सुंदर क्लंकी, और आवश्यकता है कि मैं इनपुट और आउटपुट के बीच मैपिंग में पाने के लिए स्रोत कोड को गहराई से संशोधित करूं।

ऐसा लगता है कि आप बाइनरी को विभिन्न वेरिएंट में देख सकते हैं (मेरे मामले में मैं इसे 8-बिट विखंडू में दशमलव संख्या के रूप में देखना चाहूंगा, क्योंकि यह इनपुट के बहुत करीब है)। दरअसल, कुछ संख्याएं 16 बिट, कुछ 8, कुछ 32 आदि हैं, इसलिए हो सकता है कि इनमें से प्रत्येक में बाइनरी को देखने का एक तरीका हो, जिसमें किसी न किसी तरह से मेमोरी में हाइलाइट किया गया हो।

एकमात्र तरीका जो मैं देख सकता था कि संभव है कि क्या आप वास्तव में वास्तविक द्विआधारी प्रारूप / लेआउट के लिए एक विज़ुअलाइज़र का निर्माण करते हैं। तो यह जानता है कि अनुक्रम में 32 बिट संख्या कहां होनी चाहिए, और 8 बिट संख्या कहां होनी चाहिए, आदि यह कुछ स्थितियों में बहुत काम और तरह की मुश्किल है। तो अगर वहाँ एक सामान्य तरीका यह करने के लिए सोच रहा है।

मैं यह भी सोच रहा हूं कि वर्तमान में इस प्रकार की डिबगिंग का सामान्य तरीका क्या है, इसलिए शायद मुझे इस पर कुछ विचार मिल सकते हैं।


75
आपको एक उत्तर मिला है "सीधे हेक्सडम्प का उपयोग करें, और यह और इसके अतिरिक्त करें" - और उस उत्तर को बहुत अधिक अपडाउन मिला। और एक दूसरा जवाब, 5 घंटे बाद (!), केवल "एक हेक्सडम्प का उपयोग करें" कहकर। फिर आपने पहले के पक्ष में दूसरे को स्वीकार किया? गंभीरता से?
डॉक्टर ब्राउन

4
जब आपके पास एक द्विआधारी प्रारूप का उपयोग करने का एक अच्छा कारण हो सकता है, तो विचार करें कि क्या आप केवल मौजूदा पाठ प्रारूप जैसे JSON का उपयोग कर सकते हैं। मानव की पठनीयता बहुत मायने रखती है, और मशीनें और नेटवर्क आमतौर पर इतनी तेजी से बढ़ते हैं कि आजकल आकार को कम करने के लिए कस्टम प्रारूप का उपयोग करना अनावश्यक है।
jpmc26

4
@ jpmc26 अभी भी द्विआधारी प्रारूपों के लिए बहुत अधिक उपयोग है और हमेशा रहेगा। मानव पठनीयता आमतौर पर प्रदर्शन, भंडारण आवश्यकताओं और नेटवर्क प्रदर्शन के लिए माध्यमिक होती है। और अभी भी कई क्षेत्र हैं जहां विशेष रूप से नेटवर्क का प्रदर्शन खराब है और भंडारण सीमित है। इसके अलावा विरासत प्रणाली (हार्डवेयर और सॉफ्टवेयर दोनों) के साथ इंटरफेस करने और अपने डेटा स्वरूपों का समर्थन करने वाले सभी सिस्टम को मत भूलना।
शाम

4
@jwenting नहीं, वास्तव में, डेवलपर समय आमतौर पर एक आवेदन का सबसे महंगा टुकड़ा है। यदि आप Google या फेसबुक पर काम कर रहे हैं तो निश्चित रूप से ऐसा नहीं हो सकता है, लेकिन अधिकांश ऐप उस पैमाने पर काम नहीं करते हैं। और जब आपके डेवलपर्स सामान पर समय बिता रहे हैं तो सबसे महंगा संसाधन है, मानव पठनीयता कार्यक्रम को पार्स करने के लिए 100 मिलीसेकंड से अधिक के लिए बहुत अधिक मायने रखता है।
jpmc26

3
@ jpmc26 मुझे उस प्रश्न में कुछ भी दिखाई नहीं देता जो मुझे सुझाव देता है कि ओपी प्रारूप को परिभाषित करने वाला एक है।
जिमीजैम

जवाबों:


76

तदर्थ जांच के लिए, बस एक मानक हेक्सडंप का उपयोग करें और इसे नेत्रगोलक करना सीखें।

यदि आप एक उचित जांच के लिए टूल करना चाहते हैं, तो मैं आमतौर पर पायथन जैसे कुछ में एक अलग डिकोडर लिखता हूं - आदर्श रूप से यह सीधे एक संदेश कल्पना दस्तावेज़ या आईडीएल से संचालित किया जाएगा, और जितना संभव हो उतना स्वचालित हो सकता है (इसलिए मैन्युअल रूप से शुरू करने का कोई मौका नहीं है। दोनों डिकोडर में एक ही बग)।

अंत में, मत भूलो कि आपको अपने डिकोडर के लिए यूनिट टेस्ट लिखना चाहिए, ज्ञात-सही कैन्ड इनपुट का उपयोग करके।


2
"बस एक मानक हेक्सडम्प का उपयोग करें और इसे नेत्रगोलक करना सीखें।" हाँ। मेरे अनुभव में, 200 बिट्स तक के कुछ खंडों को समूहीकृत तुलना के लिए एक व्हाइटबोर्ड पर नीचे लिखा जा सकता है, जो कभी-कभी इस तरह की चीज को शुरू करने में मदद करता है।
मस्त

1
अगर बाइनरी डेटा एप्लिकेशन (या सिस्टम, सामान्य रूप से) में एक महत्वपूर्ण भूमिका निभाता है, तो मुझे एक अलग डिकोडर अच्छी तरह से प्रयास के लायक लगता है। यह विशेष रूप से सच है यदि डेटा प्रारूप परिवर्तनशील है: निश्चित लेआउट में डेटा को थोड़े अभ्यास के साथ हेक्सडंप में देखा जा सकता है लेकिन एक प्रैक्टिसबिलिटी वॉल को तेजी से हिट करता है। हमने कमर्शियल पैकेट डिकोडर्स के साथ USB और CAN ट्रैफिक को डीबग किया, और मैंने एक PROFIBus डिकोडर (जहाँ बाइट्स में फैले चर, पूरी तरह से हेक्स डंप में अपठनीय हैं) लिखा है, और उन तीनों को बेहद मददगार पाया।
पीटर - मोनिका

10

ऐसा करने के लिए पहला कदम यह है कि आपको एक व्याकरण खोजने या परिभाषित करने के लिए एक तरीका चाहिए जो डेटा की संरचना का वर्णन करता है अर्थात एक स्कीमा।

इसका एक उदाहरण COBOL की एक भाषा विशेषता है जिसे अनौपचारिक रूप से कॉपीबुक के रूप में जाना जाता है। कोबोल कार्यक्रमों में आप मेमोरी में डेटा की संरचना को परिभाषित करेंगे। यह संरचना बाइट्स को संग्रहीत करने के तरीके से सीधे मैप की गई थी। यह उस युग की भाषाओं के लिए सामान्य सामान्य भाषाओं के विपरीत है जहां मेमोरी का भौतिक लेआउट एक कार्यान्वयन चिंता है जो डेवलपर से दूर है।

बाइनरी डेटा स्कीमा भाषा के लिए एक Google खोज कई टूल को चालू करता है। एक उदाहरण अपाचे DFDL है । इसके लिए पहले से ही UI हो सकता है।


2
यह सुविधा 'प्राचीन' युग की भाषाओं के लिए आरक्षित नहीं है। C और C ++ स्ट्रक्चर्स और यूनियनों को मेमोरी एलाइन किया जा सकता है। C # में StructLayoutAttribute है, जिसका उपयोग मैंने बाइनरी डेटा को प्रसारित करने के लिए किया है।
कैस्पर वैन डेन बर्ग

1
@KaspervandenBerg जब तक आप यह नहीं कह रहे हैं कि C और C ++ ने हाल ही में इन्हें जोड़ा है, मैं समझता हूं कि वही युग है। मुद्दा यह है कि ये प्रारूप केवल डेटा ट्रांसमिशन के लिए नहीं थे, हालांकि वे इसके लिए उपयोग किए गए थे, उन्होंने सीधे मैप किया कि कोड ने मेमोरी और डिस्क पर डेटा के साथ कैसे काम किया। यह सामान्य तौर पर नहीं है कि नई भाषाएँ कैसे काम करती हैं, हालांकि उनमें ऐसी विशेषताएं हो सकती हैं।
जिमीजैम

@KaspervandenBerg C ++ उतना नहीं करता जितना आपको लगता है कि यह करता है। कार्यान्वयन-विशिष्ट टूलींग का उपयोग करके इसे संरेखित करना और पैडिंग को समाप्त करना संभव है (और, वास्तव में, इस तरह की चीज़ के लिए मानक तेजी से सुविधाओं को जोड़ रहा है) और सदस्य आदेश नियतात्मक है (लेकिन जरूरी नहीं कि स्मृति में भी ऐसा ही हो!)।
ऑर्बिट

6

ASN.1 , सार सिंटेक्स नोटेशन वन, एक द्विआधारी प्रारूप को निर्दिष्ट करने का एक तरीका प्रदान करता है।

  • डीडीटी - नमूना डेटा और यूनिट परीक्षणों का उपयोग करके विकसित करना।
  • एक पाठकीय डंप मददगार हो सकता है। अगर XML में आप subhierarchies को ध्वस्त / विस्तारित कर सकते हैं।
  • ASN.1 की वास्तव में जरूरत नहीं है, लेकिन एक व्याकरण आधारित है, और अधिक घोषणा फ़ाइल विनिर्देश आसान है।

6
यदि ASN.1 पार्सरों में सुरक्षा कमजोरियों की कभी न खत्म होने वाली परेड कोई संकेत है, तो इसे अपनाने से निश्चित रूप से बाइनरी प्रारूपों को डीबग करने में अच्छा व्यायाम मिलेगा।
मार्क

1
@ मर्क कई छोटी बाइट सरणियों (और यह कि अलग-अलग पदानुक्रम पेड़ों में) अक्सर सी में सही (सुरक्षित रूप से) को संभाला नहीं जाता है (उदाहरण के लिए अपवादों का उपयोग नहीं करना)। कभी भी निम्न-स्तर को कम न समझें, उदाहरण के लिए, सी। ASN.1 की अंतर्निहित अनिश्चितता - जावा इस समस्या को उजागर नहीं करता है। ASN.1 व्याकरण निर्देशित पार्सिंग को सुरक्षित रूप से किया जा सकता है, यहां तक ​​कि C को एक छोटे और सुरक्षित कोड बेस के साथ भी किया जा सकता है। और कमजोरियों का हिस्सा द्विआधारी प्रारूप में ही निहित है: एक प्रारूप के व्याकरण के "कानूनी" निर्माण का शोषण कर सकता है, जिसमें विनाशकारी शब्दार्थ हैं।
जोप एगेनजेन

3

अन्य उत्तरों में हेक्स डंप देखने, या जेएसएन में ऑब्जेक्ट स्ट्रक्चर्स को लिखने का वर्णन किया गया है। मुझे लगता है कि इन दोनों को मिलाना बहुत मददगार है।

एक उपकरण का उपयोग करना जो हेक्स डंप के शीर्ष पर JSON को प्रस्तुत कर सकता है, वास्तव में उपयोगी है; मैंने एक ओपन सोर्स टूल लिखा है, जो कि डॉट नेटबाइट्स नामक .NET बायनेरीज़ को पार्स करता है , यहाँ एक उदाहरण DLL का एक दृश्य है

dotNetBytes उदाहरण


1

मुझे यकीन नहीं है कि मैं पूरी तरह से समझता हूं, लेकिन ऐसा लगता है कि आपके पास इस द्विआधारी प्रारूप के लिए एक पार्सर है, और आप इसके लिए कोड को नियंत्रित करते हैं। तो यह जवाब उस धारणा पर बनाया गया है।

एक पार्सर किसी भी तरह से आपकी भाषा की संरचना, वर्ग, या जो भी डेटा संरचना है, उसे भर रहा होगा। यदि आप ToStringउन सभी चीज़ों के लिए कार्यान्वित करते हैं जो पार्स हो जाती हैं, तो आप एक बाइनरी डेटा को मानव पठनीय प्रारूप में प्रदर्शित करने के लिए उपयोग करने के लिए बहुत आसानी से और आसानी से बनाए रखने की विधि के साथ समाप्त होते हैं।

आप अनिवार्य रूप से होगा:

byte[] arrayOfBytes; // initialized somehow
Object obj = Parser.parse(arrayOfBytes);
Logger.log(obj.ToString());

और वह यह है, इसका उपयोग करने के दृष्टिकोण से। बेशक इसके लिए आपको ToStringअपनी Objectकक्षा / संरचना / जो कुछ भी है, उसके लिए फ़ंक्शन को लागू करना / ओवरराइड करना होगा, और आपको किसी भी नेस्टेड वर्ग / स्ट्रक्चर / व्हाईवर्स के लिए भी ऐसा करना होगा।

ToStringफ़ंक्शन को रिलीज़ कोड में कॉल करने से रोकने के लिए आप अतिरिक्त रूप से एक सशर्त कथन का उपयोग कर सकते हैं ताकि आप किसी ऐसी चीज़ पर समय बर्बाद न करें जो डीबग मोड के बाहर लॉग इन नहीं होगी।

आपका ऐसा ToStringदिख सकता है:

return String.Format("%d,%d,%d,%d", int32var, int16var, int8var, int32var2);

// OR

return String.Format("%s:%d,%s:%d,%s:%d,%s:%d", varName1, int32var, varName2, int16var, varName3, int8var, varName4, int32var2);

आपका मूल प्रश्न यह ध्वनि करता है जैसे आपने कुछ ऐसा करने का प्रयास किया है, और आपको लगता है कि यह विधि बोझ है, लेकिन आपने कुछ बिंदुओं पर एक द्विआधारी प्रारूप को लागू करने और उस डेटा को संग्रहीत करने के लिए चर भी बनाए हैं। तो आपको बस इतना करना होगा कि उन मौजूदा वेरिएबल्स को एब्स्ट्रैक्शन के उपयुक्त स्तर पर प्रिंट करें (वेरिएबल जिस क्लास / स्ट्रक्चर में है)।

यह कुछ ऐसा है जो आपको केवल एक बार करना चाहिए, और आप इसे पार्सर बनाते समय कर सकते हैं। और यह केवल तभी बदलेगा जब बाइनरी प्रारूप में परिवर्तन होगा (जो पहले से ही आपके पार्सर वैसे भी बदलाव का संकेत देगा)।

इसी तरह की नस में: कुछ भाषाओं में एक्सएमएल या जेएसएन में कक्षाएं बदलने की मजबूत विशेषताएं हैं। C # इस पर विशेष रूप से अच्छा है। आपको अपने द्विआधारी प्रारूप को छोड़ने की ज़रूरत नहीं है, आप बस XML या JSON को डिबग लॉगिंग स्टेटमेंट में करते हैं और अपने रिलीज़ कोड को अकेले छोड़ देते हैं।

मैं व्यक्तिगत रूप से हेक्स डंप मार्ग पर नहीं जाने की सलाह दूंगा, क्योंकि यह त्रुटियों से ग्रस्त है (क्या आपने सही बाइट पर शुरू किया था, क्या आप सुनिश्चित हैं कि जब आप बाएं से दाएं पढ़ रहे हैं तो आप सही धीरज, आदि "देख रहे हैं") ।

उदाहरण: अपने ToStringsथूक को चर कहो a,b,c,d,e,f,g,h। आप अपना प्रोग्राम चलाते हैं और बग को नोटिस करते हैं g, लेकिन समस्या वास्तव में शुरू हुई c(लेकिन आप डिबगिंग कर रहे हैं, इसलिए आपने अभी तक इसका पता नहीं लगाया है)। यदि आप इनपुट मान जानते हैं (और आपको चाहिए) तो आप तुरंत देखेंगे कि cसमस्याएँ कहाँ से शुरू होती हैं।

एक हेक्स डंप की तुलना में जो आपको बताता है 338E 8455 0000 FF76 0000 E444 ....; यदि आपके क्षेत्र अलग-अलग आकार के हैं, तो कहां से cशुरू होता है और क्या मूल्य है - एक हेक्स संपादक आपको बताएगा लेकिन मेरी बात यह है कि त्रुटि प्रवण और समय लेने वाली है। इतना ही नहीं, लेकिन आप आसानी से / जल्दी से एक हेक्स दर्शक के माध्यम से एक परीक्षण को स्वचालित नहीं कर सकते। डेटा को पार्स करने के बाद एक स्ट्रिंग प्रिंट करना आपको यह बताएगा कि आपका कार्यक्रम 'सोच' क्या है, और स्वचालित परीक्षण के मार्ग के साथ एक कदम होगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.