अपने कोड में अवांछित बग को प्रकट करने के लिए जीएनयू डिबगर का उपयोग करना सीखकर कोड गुणवत्ता में सुधार करें और अप्रत्याशित परिणामों को रोकें।
डिबगिंग प्रोग्रामर और सुरक्षा शोधकर्ताओं के लिए एक अनिवार्य कौशल है। डिबगिंग पर मजबूत पकड़ होने से आप निचले स्तर पर निष्पादन योग्य को समझ सकते हैं और किसी भी छिपी हुई त्रुटि को पकड़ सकते हैं।
जीएनयू डिबगर या, जीडीबी, एक कालातीत डिबगिंग टूल है जिस पर प्रोग्रामर वर्षों से भरोसा कर रहे हैं। यहां Linux पर GDB का उपयोग करने का तरीका बताया गया है.
नमूना कार्यक्रम तैयार करना
जीडीबी की विशेषताओं का पता लगाने के लिए आपको प्रयोग करने के लिए एक निष्पादन योग्य की आवश्यकता होगी। प्रदर्शन के लिए, आप एक बार स्रोत कोड और डिबग प्रतीकों के साथ कुंजी-जांच कार्यक्रम पर जीडीबी चलाएंगे, एक बार बिना स्रोत कोड, और एक साधारण मल्टीथ्रेडेड प्रोग्राम पर जो संदेशों को स्क्रीन पर प्रिंट करता है, दोनों सी में लिखे गए हैं और जीसीसी (जीएनयू सी) के साथ संकलित हैं संकलक)।
तुम कर सकते हो किसी अन्य C कंपाइलर का उपयोग करें लेकिन सुनिश्चित करें कि बाइनरी को अलग न करें।
आप संभवतः अपने स्वयं के प्रोग्रामों पर GDB चला रहे होंगे। इसलिए उन्हें संकलित करना सुनिश्चित करें
-जी डिबग प्रतीकों को सक्षम करने के लिए जीसीसी के साथ ध्वजांकित करें।मौजूद डिबग प्रतीकों के बिना और भारी छीनी गई बाइनरी के साथ, आपको प्रोग्राम के डिस्सेम्बली को डीबग करना होगा। इसके लिए आपको असेंबली लैंग्वेज पर मजबूत पकड़ होनी चाहिए लिनक्स पर मेमोरी आवंटन कैसे काम करता है स्टैक और रजिस्टरों में डेटा को समझने के लिए।
GDB में एक प्रोग्राम चला रहा हूँ
आप GDB में कुछ तरीकों से एक प्रोग्राम चलाते हैं। या तो टाइप करें जीडीबी , और एक बार यह लोड हो जाए तो टाइप करें दौड़ना. या gdb प्रारंभ करें और फिर इसका उपयोग करें फ़ाइल कमांड, बाइनरी को जीडीबी में लोड करें, और फिर इसे निष्पादित करें दौड़ना आज्ञा।
यदि आपके प्रोग्राम को ठीक से काम करने के लिए कमांड-लाइन तर्कों की आवश्यकता है, तो प्रोग्राम नाम के बाद तर्क जोड़ना सुनिश्चित करें। प्रोग्राम को GDB पर लोड करने और इसे तर्कों के साथ निष्पादित करने का सिंटैक्स यहां दिया गया है:
gdb
run
या:
gdb
file
run
जीडीबी के साथ ब्रेकप्वाइंट सेट करना
डिबगिंग में ब्रेकप्वाइंट को मैन्युअल रूप से कोड में हार्ड स्टॉप सेट किया जाता है जो प्रोग्राम के ब्रेकप्वाइंट पर पहुंचने पर निष्पादन के प्रवाह को रोक देता है। ब्रेकप्वाइंट सेट करने से आप कोड के माध्यम से कदम बढ़ा सकते हैं और निरीक्षण कर सकते हैं कि निष्पादन का प्रत्येक चरण डेटा और वेरिएबल्स को कैसे प्रभावित करता है।
जीडीबी में, जब आप डिबग प्रतीकों के साथ किसी प्रोग्राम को डिबग कर रहे होते हैं, तो आप या तो फ़ंक्शन के नाम से ब्रेकपॉइंट सेट कर सकते हैं या लाइन नंबर के आधार पर ब्रेकपॉइंट सेट कर सकते हैं। यहाँ वाक्यविन्यास है:
break main
break 47
वर्तमान डिबगिंग सत्र में सभी ब्रेकप्वाइंट देखने के लिए, टाइप करें:
info breakpoints
किसी विशेष ब्रेकप्वाइंट या एकाधिक ब्रेकप्वाइंट को हटाने के लिए, टाइप करें:
delete 2
delete 3-5
जीडीबी आपको सशर्त ब्रेकप्वाइंट सेट करने की भी अनुमति देता है, जिसका अर्थ है कि प्रोग्राम केवल तभी रुकेगा जब निष्पादन के दौरान कोई विशेष शर्त पूरी हो जाएगी। यह किसी वेरिएबल के मान में परिवर्तन या असफल फ़ंक्शन कॉल या, जो कुछ भी आप चाहते हैं, हो सकता है। सशर्त ब्रेकप्वाइंट सेट करने का सिंटैक्स यहां दिया गया है:
break if n == 2
यदि आप ब्रेकप्वाइंट पर पहुंचने के बाद प्रोग्राम का निष्पादन जारी रखना चाहते हैं, तो टाइप करें जारी रखना आज्ञा:
continue
कोड के माध्यम से कदम उठाना
यह समझने के लिए कि प्रोग्राम डेटा को कैसे प्रबंधित कर रहा है, कोड के माध्यम से कदम उठाना महत्वपूर्ण है। अपने प्रोग्राम में विभिन्न कार्यों के माध्यम से कदम उठाकर और डेटा की स्थिति की जांच करके, आप इस बात की बेहतर समझ प्राप्त कर सकते हैं कि प्रोग्राम आपके द्वारा कोड में लिखे गए तर्क को कैसे कार्यान्वित कर रहा है।
यह आपको क्रैश की जड़ का पता लगाने और सर्जिकल परिशुद्धता के साथ प्रोग्राम व्यवहार का अध्ययन करने में भी मदद करता है क्योंकि आप अपनी इच्छानुसार कोड की प्रत्येक पंक्ति के माध्यम से कदम उठाने में सक्षम होते हैं। आप GDB में तीन प्राथमिक तरीकों से कोड को पार कर सकते हैं:
- कदम: यह कमांड GDB को स्रोत फ़ाइल की अगली पंक्ति में कदम रखने के लिए कहता है। यह आपको अनिवार्य रूप से स्रोत कोड की लंबाई को लाइन दर लाइन पार करने की अनुमति देता है।
- अगला: यह कमांड वर्तमान फ़ंक्शन के अंदर स्रोत कोड की अगली पंक्ति को निष्पादित करता है और फिर रुक जाता है। अगला किसी फ़ंक्शन को एक पंक्ति के रूप में मानता है, इसलिए यदि आप फ़ंक्शन कॉल से पहले अगला उपयोग करते हैं, तो यह इसे एक पंक्ति के रूप में मान लेगा और इसके विपरीत, इसके ऊपर कदम रखेगा कदम आज्ञा।
- खत्म करना: फ़िनिश कमांड वर्तमान फ़ंक्शन के अंदर शेष सभी पंक्तियों को निष्पादित करता है और फिर रुक जाता है।
चरों की जांच करना
जैसे ही आप कोड के माध्यम से आगे बढ़ते हैं, आप यह देखने के लिए वेरिएबल्स के मान की जांच करना चाहेंगे कि प्रोग्राम तर्क उन्हें कैसे बदल रहा है। GDB में वेरिएबल्स का मान देखने के लिए सिंटैक्स यहां दिया गया है:
print
यदि आप हर बार अपडेट होने पर किसी वेरिएबल के मान में परिवर्तन प्रिंट करना चाहते हैं, तो आपको डिस्प्ले कमांड का उपयोग करना चाहिए। यह विशेष रूप से तब उपयोगी होता है जब आप किसी लूप में किसी वेरिएबल के मान को ट्रैक और प्रिंट करना चाहते हैं:
display
निगरानी बिंदु निर्धारित करना
वॉचप्वाइंट और सशर्त ब्रेकप्वाइंट बारीकी से संबंधित हैं क्योंकि वे दोनों एक कार्यक्रम में बदलावों पर प्रतिक्रिया करते हैं। कोड में डेटा में परिवर्तन को ट्रैक करने के लिए वॉचपॉइंट का उपयोग किया जाता है। उदाहरण के लिए, हो सकता है कि आप चाहें कि जब भी किसी वेरिएबल का मान बदल जाए तो प्रोग्राम ब्रेक हो जाए। यहां GDB के साथ ऐसा करने का तरीका बताया गया है:
watch
जीडीबी के साथ थ्रेड-विशिष्ट डिबगिंग
मल्टीथ्रेडेड प्रोग्राम के साथ काम करते समय जीडीबी आपको थ्रेड-विशिष्ट डिबगिंग करने की अनुमति देता है। प्रदर्शन के लिए, हम एक सरल सी प्रोग्राम के साथ काम करेंगे जो प्रत्येक थ्रेड के साथ संदेशों को प्रिंट करने के लिए चार थ्रेड का उपयोग करता है।
अपने प्रोग्राम में वर्तमान में उत्पन्न थ्रेड्स को देखने के लिए, का उपयोग करें जानकारी आज्ञा:
info threads
किसी विशिष्ट थ्रेड के साथ काम करने के लिए, आप इसकी अनुक्रमणिका संख्या का उपयोग करके इसे सूची से चुन सकते हैं। उदाहरण के लिए:
thread 2
थ्रेड का चयन करने के बाद आप इसका उपयोग करके इसके निष्पादन प्रवाह के माध्यम से आगे बढ़ सकते हैं कदम, अगला, और खत्म करना जैसा कि ऊपर दिखाया गया है आदेश।
जीडीबी के साथ रिमोट डिबगिंग
आप किसी भिन्न सिस्टम पर स्थित प्रोग्राम को दूरस्थ रूप से डीबग भी कर सकते हैं। ऐसा करने के लिए, आपको लक्ष्य मशीन पर gdbserver सेट अप करना होगा। आप इसे अपने वितरण के डिफ़ॉल्ट पैकेज मैनेजर का उपयोग करके आसानी से इंस्टॉल कर सकते हैं आपके द्वारा स्थापित अन्य पैकेज प्रबंधक आपके सिस्टम पर.
उदाहरण के लिए, अपने उबंटू या डेबियन-आधारित सिस्टम पर gdbserver स्थापित करने के लिए, APT का उपयोग करें:
sudo apt install gdbserver
एक बार इंस्टॉल हो जाने पर, बाइनरी के फ़ोल्डर में जाएं और gdbserver प्रारंभ करने के लिए यह कमांड चलाएँ:
gdbserver :
gdbserver को वह आउटपुट लौटाना चाहिए जो वह चालू है और आपके द्वारा परिभाषित पोर्ट पर सुन रहा है। अब क्लाइंट मशीन पर, GDB प्रारंभ करें और फिर का उपयोग करके रिमोट सर्वर से कनेक्ट करें लक्ष्य आज्ञा:
target remote :
डिबगिंग को स्वचालित करने के लिए GDB स्क्रिप्ट लिखना
GDB प्रोग्रामर्स को GDB स्क्रिप्ट लिखने की अनुमति देता है जो GDB कमांड को स्वचालित रूप से निष्पादित करेगा। जब आप किसी कोड के एक ही हिस्से को कई बार डीबग करने का प्रयास कर रहे हों तो इससे बहुत मदद मिलती है। हर बार जब आप बाइनरी लोड करते हैं तो ब्रेकपॉइंट सेट करने, कोड के माध्यम से कदम उठाने और वैरिएबल मान प्रिंट करने के बजाय, आप पूरी प्रक्रिया को स्वचालित करने के लिए जीडीबी स्क्रिप्ट का उपयोग कर सकते हैं।
यहाँ एक उदाहरण है:
set logging enabled on
set logging file sample.out
break main
command 1
backtrace
print N
continue
end
quit
उपरोक्त स्क्रिप्ट में, आप जीडीबी को लॉगिंग सक्षम करने और लॉग को नामक फ़ाइल में सहेजने के लिए कह रहे हैं नमूना.बाहर, फिर एक ब्रेकप्वाइंट सेट करें मुख्य समारोह।
ब्रेकप्वाइंट नंबर 1 के लिए, इस मामले में, फ़ंक्शन मुख्य पर ब्रेकप्वाइंट, निम्नलिखित कमांड चलाएँ: पश्व-अनुरेखन, छपाई, जारी रखना. मूल रूप से, जीडीबी पहले एक बैकट्रेस चलाएगा, फिर वेरिएबल "एन" का मान प्रिंट करेगा, निष्पादन जारी रखेगा और अंत में छोड़ देगा।
इस स्क्रिप्ट को निष्पादित करने के लिए, उपयोग करें:
gdb -x