C ++ में सेगमेंटेशन दोषों को ठीक करना


95

मैं विंडोज और यूनिक्स के लिए एक क्रॉस-प्लेटफॉर्म सी ++ प्रोग्राम लिख रहा हूं। विंडो साइड पर, कोड कोई समस्या संकलित और निष्पादित करेगा। यूनिक्स की तरफ, हालांकि यह संकलित करेगा जब मैं इसे चलाने की कोशिश करता हूं, मुझे एक विभाजन दोष मिलता है। मेरा प्रारंभिक कूबड़ है कि वहाँ संकेत के साथ एक समस्या है।

विभाजन की त्रुटियों को खोजने और उन्हें ठीक करने के लिए अच्छी कार्यप्रणालियाँ क्या हैं?

जवाबों:


134
  1. अपने एप्लिकेशन को इसके साथ संकलित करें -g, फिर आपके पास बाइनरी फ़ाइल में डिबग प्रतीक होंगे।

  2. gdbGdb कंसोल को खोलने के लिए उपयोग करें ।

  3. fileकंसोल में अपने एप्लिकेशन की बाइनरी फ़ाइल का उपयोग करें और इसे पास करें ।

  4. runअपने आवेदन को शुरू करने के लिए किसी भी दलील का उपयोग करें और पास करें ।

  5. एक विभाजन दोष का कारण कुछ करो ।

  6. सेगमेंटेशन फ़ॉल्ट का स्टैक ट्रेस प्राप्त करने के लिए कंसोल btमें टाइप करें ।gdb


इसके gसंदर्भ में संकलित करने का क्या मतलब है CMake?
Schütze

2
डीबग बिल्ड प्रकार सक्षम करें। एक तरीका है cmake -DCMAKE_BUILD_TYPE=Debug
एंटोनिन डेसीमो

36

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


19

समस्या उत्पन्न होने से पहले, जितना संभव हो इससे बचने की कोशिश करें:

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

डिबगिंग के लिए उपयुक्त टूल का उपयोग करें। यूनिक्स पर:

  • GDB आपको बता सकता है कि आप कहां क्रैश करते हैं और आपको किस संदर्भ में देखने देगा।
  • Valgrind आपको मेमोरी से संबंधित कई त्रुटियों का पता लगाने में मदद करेगा।
  • जीसीसी के साथ आप जीसीसी, क्लैंग के साथ मडफ्लैप का भी उपयोग कर सकते हैं और अक्टूबर से प्रयोगात्मक रूप से MSVC के बाद आप एड्रेस / मेमोरी सैनिटाइजर का उपयोग कर सकते हैं । यह कुछ त्रुटियों का पता लगा सकता है जो Valgrind नहीं करता है और प्रदर्शन हानि हल्का है। इसका उपयोग -fsanitize=addressध्वज के साथ संकलन करके किया जाता है ।

अंत में मैं सामान्य चीजों की सिफारिश करूंगा। आपका कार्यक्रम जितना अधिक पठनीय, रखरखाव योग्य, स्पष्ट और साफ-सुथरा होगा, उतना ही आसान यह डिबग करना होगा।


5

यूनिक्स पर आप valgrindमुद्दों को खोजने के लिए उपयोग कर सकते हैं। यह स्वतंत्र और शक्तिशाली है। यदि आप इसे स्वयं करते हैं, तो आप एक नया सेटअप करने से पहले और उसके बाद एक कॉन्फ़िगरेशन सेट करने के लिए ओवरलोड newऔर deleteऑपरेटर्स को अधिभारित कर सकते हैं 0xDEADBEEF। फिर ट्रैक करें कि प्रत्येक पुनरावृत्ति पर क्या होता है। यह सब कुछ पकड़ने में विफल हो सकता है (आप उन बाइट्स को छूने की भी गारंटी नहीं देते हैं) लेकिन यह मेरे लिए विंडोज प्लेटफॉर्म पर अतीत में काम कर चुका है।


1
अच्छी तरह से यह 1 के बजाय 4 बाइट्स होगा ... लेकिन सिद्धांत ठीक है।
जोनास वैगनर

1
क्या मैं अपने गैर-दखल देने वाले ढेर डिबगर से जुड़ सकता हूं ? :-)
fredoverflow

इसका लाभ उठाएं। हम यहाँ दूसरों की मदद करने के बारे में बहुत कुछ कर रहे हैं, जिससे कुछ भी जोड़ा जा सकता है।
गेहूँ

हालांकि ओवरलोडिंग newऔर deleteसुपर उपयोगी हो सकता है, का उपयोग -fsanitize=addressकरना एक बेहतर विकल्प है क्योंकि कंपाइलर समस्याओं के लिए रनटाइम डिटेक्शन में संकलित करेगा और मेमोरी को स्क्रीन पर स्वचालित रूप से डंप करेगा जो डिबगिंग का रास्ता आसान बनाता है।
टार्क वेलिंग

3

हाँ, वहाँ संकेत के साथ एक समस्या है। बहुत संभावना है कि आप एक का उपयोग कर रहे हैं जिसे ठीक से आरंभीकृत नहीं किया गया है, लेकिन यह भी संभव है कि आप अपने मेमोरी मैनेजमेंट को डबल फ्रीज़ या कुछ इस तरह से गड़बड़ कर रहे हों।

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

सदस्य मूल्यों के रूप में अनइंस्टॉल किए गए पॉइंटर्स से बचने के लिए, सुनिश्चित करें कि वे कंस्ट्रक्टर में ठीक से आरंभीकृत हैं, और कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटरों में ठीक से संभाले हुए हैं। initस्मृति प्रबंधन के लिए एक फ़ंक्शन पर भरोसा मत करो , हालांकि आप अन्य इनिशियलाइज़ेशन के लिए कर सकते हैं।

यदि आपकी कक्षा को कॉपी कंस्ट्रक्टर या असाइनमेंट ऑपरेटरों की आवश्यकता नहीं है, तो आप उन्हें निजी सदस्य कार्यों के रूप में घोषित कर सकते हैं और उन्हें कभी परिभाषित नहीं कर सकते। यदि वे स्पष्ट रूप से या अंतर्निहित रूप से उपयोग किए जाते हैं तो एक संकलक त्रुटि का कारण होगा।

लागू होने पर स्मार्ट पॉइंटर्स का उपयोग करें। यहां बड़ा फायदा यह है कि, यदि आप उनसे चिपके रहते हैं और लगातार उनका उपयोग करते हैं, तो आप पूरी तरह से लिखने से बच सकते हैं deleteऔर कुछ भी डबल डिलीट नहीं होगा।

सी-स्टाइल स्ट्रिंग्स और सरणियों के बजाय, जब भी संभव हो सी ++ स्ट्रिंग्स और कंटेनर कक्षाओं का उपयोग करें। .at(i)इसके बजाय का उपयोग करने पर विचार करें [i], क्योंकि यह सीमा की जाँच को मजबूर करेगा। देखें कि क्या आपका संकलक या पुस्तकालय सीमा को [i]कम से कम डिबग मोड पर जाँचने के लिए सेट किया जा सकता है। सेगमेंटेशन दोष बफर ओवररन के कारण हो सकते हैं जो पूरी तरह से अच्छे बिंदुओं पर कचरा लिखते हैं।

उन चीजों को करने से विभाजन दोष और अन्य स्मृति समस्याओं की संभावना कम हो जाएगी। वे निस्संदेह सब कुछ ठीक करने में विफल रहेंगे, और इसीलिए जब आपको कोई समस्या नहीं है, तो आपको अभी और तब वैग्रिंड का उपयोग करना चाहिए, और जब आप करते हैं तो वैग्रिड और जीडीबी।


1

मैं इस तरह से चीजों को ठीक करने के लिए उपयोग करने के लिए किसी भी पद्धति का पता नहीं है। मुझे नहीं लगता कि हाथ में बहुत ही मुद्दे के लिए एक के साथ आना संभव होगा, यह है कि आपके कार्यक्रम का व्यवहार अपरिभाषित है (मुझे किसी भी मामले का पता नहीं है जब SEGFAULT किसी प्रकार के यूबी के कारण नहीं हुआ है) ।

समस्या उत्पन्न होने से पहले सभी तरह की "कार्यप्रणाली" होती है। एक महत्वपूर्ण RAII है।

इसके अलावा, आपको बस उस पर अपनी सर्वश्रेष्ठ मानसिक ऊर्जा फेंकनी होगी।

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