2010-09-15 2 views
46

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

सेगमेंटेशन गलती त्रुटियों को ढूंढने और ठीक करने के लिए क्या अच्छी पद्धतियां हैं?

उत्तर

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

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

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

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

  5. सेगमेंटेशन फॉल्ट का कारण बनने के लिए कुछ करें।

  6. gdb कंसोल में टाइप btविभाजन दोष की एक स्टैक ट्रेस प्राप्त करने के लिए।

2

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

+1

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

+0

क्या मैं अपने [गैर-घुसपैठ ढेर डीबगर] से लिंक कर सकता हूं (http://stackoverflow.com/questions/2835416)? :-) – fredoverflow

+0

इसके लिए जाएं। हम यहां दूसरों की मदद करने के बारे में सब कुछ कर रहे हैं ताकि मदद की जा सके। – wheaties

22

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

14

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

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

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

  • GDB आपको बता सकता है कि आप प्रोग्राम कहां दुर्घटनाग्रस्त हैं और आपको किस संदर्भ में देखने देंगे।
  • Valgrind आपको कई स्मृति-संबंधी त्रुटियों का पता लगाने में मदद करेगा।
  • जीसीसी के साथ आप mudflap का उपयोग भी कर सकते हैं जीसीसी और क्लैंग के साथ आप Address/Memory Sanitizer का उपयोग कर सकते हैं। यह कुछ त्रुटियों का पता लगा सकता है जो Valgrind नहीं करता है और प्रदर्शन हानि हल्का है।

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

0

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

इससे पहले इस मुद्दे से बचने के लिए सभी प्रकार की "पद्धतियां" हैं। एक महत्वपूर्ण एक राय है।

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

2

हां, पॉइंटर्स के साथ कोई समस्या है। बहुत संभावना है कि आप उस व्यक्ति का उपयोग कर रहे हैं जो ठीक से शुरू नहीं हुआ है, लेकिन यह भी संभव है कि आप दोहरी फ्री या कुछ ऐसे के साथ अपने मेमोरी प्रबंधन को गड़बड़ कर रहे हों।

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

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

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

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

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

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