एक विभाजन दोष क्या है?


598

एक विभाजन दोष क्या है? क्या यह C और C ++ में भिन्न है? विभाजन दोष और लटकने वाले बिंदु कैसे संबंधित हैं?



22
यदि ऐसा है, तो मेरे मामले में संकलक ने कुछ भी शिकायत क्यों नहीं की, यह सब सुचारू रूप से चला गया, लेकिन समय पर सिस्टम एक विभाजन दोष (कोर डंप) फेंकता है? T_T
जिम रेन्नोर

3
बस एक मेमोरी डंप जब कुछ गलत हो जाता है!
resultsway

7
@pinouchon: मज़ेदार, लेकिन जब संकलक के पास seg faults का कोई काम होता है? क्या यह रन टाइम एनवायरमेंट नहीं है?
dhein

1
आमतौर पर एक अशक्त सूचक को हटाने का प्रयास करके बुलाया जाता है, इसलिए एक विभाजन दोष अक्सर एक जावा के अनुरूप होता है NullPointerException
रायडवल

जवाबों:


673

सेगमेंटेशन दोष एक विशिष्ट प्रकार की त्रुटि है जो मेमोरी तक पहुंचने के कारण होती है जो "आपके पास नहीं है।" यह एक सहायक तंत्र है जो आपको मेमोरी को दूषित करने और हार्ड-टू-डिबग मेमोरी बग्स को पेश करने से रोकता है। जब भी आपको एक सेगफॉल्ट मिलता है, तो आप जानते हैं कि आप मेमोरी के साथ कुछ गलत कर रहे हैं - ऐसे वेरिएबल को एक्सेस करना जो पहले ही मुक्त हो चुका है, मेमोरी के केवल-पढ़ने वाले हिस्से को लिखना, आदि सेग्मेंटेशन दोष अनिवार्य रूप से अधिकांश भाषाओं में समान है जो आपको गड़बड़ करते हैं। स्मृति प्रबंधन, सी और सी ++ में segfaults के बीच कोई मुख्य अंतर नहीं है।

सीगफॉल्ट प्राप्त करने के कई तरीके हैं, कम से कम निचले स्तर की भाषाओं जैसे सी (++) में। एक segfault पाने के लिए एक सामान्य तरीका एक अशक्त सूचक है:

int *p = NULL;
*p = 1;

एक अन्य सेगफॉल्ट तब होता है जब आप मेमोरी के एक हिस्से को लिखने की कोशिश करते हैं जिसे केवल-पढ़ने के लिए चिह्नित किया गया था:

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

डैंग्लिंग पॉइंटर एक ऐसी चीज़ की ओर इशारा करता है जो किसी भी तरह से मौजूद नहीं है, जैसे यहाँ:

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

पॉइंटर pखतरे में है क्योंकि यह वर्ण चर को इंगित करता है cजो ब्लॉक समाप्त होने के बाद अस्तित्व में नहीं रहता है। और जब आप संकेतक (जैसे *p='A') को झूलने की कोशिश करते हैं , तो आपको शायद एक segfault मिलेगा।


154
अंतिम उदाहरण विशेष रूप से बुरा है, जब मैं निर्माण करता हूं: इंट मुख्य () {चार * पी = 0; {चार सी = 'एक्स'; p = & c; } प्रिंटफ ("% c \ n", * p); वापसी 0; } या तो जीसीसी या कई अन्य संकलक के साथ, यह काम करने के लिए 'प्रकट' होता है। संकलन पर कोई चेतावनी नहीं। कोई सेगफ़ॉल्ट नहीं। ऐसा इसलिए है क्योंकि '}' आउट ऑफ स्कोप, वास्तव में डेटा को डिलीट नहीं करता है, बस इसे फिर से उपयोग किए जाने के लिए नि: शुल्क चिह्नित करता है। कोड उत्पादन प्रणाली पर वर्षों तक ठीक चल सकता है, आप कोड के किसी अन्य भाग को बदल देते हैं, संकलक या कुछ और बदल देते हैं और बोलोओम!
क्रिस हुआंग-लीवर

36
टक्कर के लिए क्षमा करें, लेकिन सिर्फ एक पक्ष ध्यान दें ... आपके उदाहरणों में से कोई भी जरूरी नहीं कि एक segfault का कारण बनता है, वास्तव में यह सिर्फ अपरिभाषित व्यवहार ;-)
Oldrinb

18
@oldrinb: यह कोड लिखना असंभव है जो जरूरी सेगफॉल्ट का कारण बनता है। कम से कम क्योंकि वहाँ ऐसे सिस्टम हैं जो मेमोरी प्रोटेक्शन के बिना काम करते हैं, इस प्रकार यह नहीं बता सकते हैं कि क्या मेमोरी का एक टुकड़ा वास्तव में "आप का है", और इस प्रकार सेगफॉल्ट्स को नहीं जानते हैं , केवल अपरिभाषित व्यवहार ... (उदाहरण के लिए, क्लासिक AmigaOS)
देवसोलर

7
@ क्रिसहुआंग-लीवर, आपको यह समझने की आवश्यकता है कि cयह स्थानीय है, इसका मतलब है कि इसे स्टैक पर धकेल दिया गया है {और इसके बाद पॉप-एड किया गया है }। डैंगलिंग पॉइंटर केवल एक ऑफसेट का संदर्भ है जो अब स्टैक से बाहर है। यही कारण है कि एक साधारण कार्यक्रम में इसे संशोधित करना कभी भी किसी सेगफॉल्ट को ट्रिगर नहीं करेगा। दूसरी ओर यह अधिक जटिल उपयोग के मामले में सेगफॉल्ट का कारण बन सकता है, जहां अन्य फ़ंक्शन कॉल स्टैक को बढ़ने और झूलने वाले सूचक द्वारा इंगित किए गए डेटा को शामिल कर सकते हैं। उस डेटा (स्थानीय संस्करण) पर लिखना अपरिभाषित व्यवहार को बढ़ावा देगा (
seffault

3
@ क्रिसहुआंग-लीवर, आम तौर पर जब आप दायरे से बाहर निकलते हैं, तो संकलक को अप्रयुक्त स्टैक स्थान को मुक्त करने के लिए कुछ स्टैक स्पेस को पुनर्प्राप्त करना पड़ता है, लेकिन ऐसा हमेशा नहीं होता है (जीसीसी इस कंपाइलर में से एक होने के साथ)। इसके अलावा, आवंटित स्टैक स्थान को सामान्य रूप से फिर से उपयोग किया जाता है, इसलिए मैंने बिना ऑपरेटिंग स्टैक के सिस्टम के लिए कोई भी ऑपरेटिंग सिस्टम वापस करने के बारे में सुना है, जिससे उस स्थान को एक विषय बना दिया जाता है SIGSEGV, इसलिए मुझे स्टैक के साथ छेड़छाड़ से ऐसे संकेत की उम्मीद नहीं होगी।
लुइस कोलोराडो

111

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

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

और यह सब वर्चुअल मेमोरी सिस्टम के संबंध में है।


साझा मेमोरी / मेमोरी मैप्ड फ़ाइलों के साथ किसी और के लिए आपकी मेमोरी के साथ गड़बड़ करना संभव है। WIN32 में 'एपीआईप्रोसेमेसेरी' जैसे नॉटी एपीआई भी हैं!
पल्म १m

1
@ अंपुलम: हां, मुझे पता है। यह मेरे दिमाग में "और शमत की तरह बातें;) - ये वही हैं जो मैं 'अप्रत्यक्ष' पहुंच के रूप में गिनता हूं।"
konrad.kruczynski

एक वर्चुअल मेमोरी ऑपरेटिंग सिस्टम में कोई रास्ता नहीं है (सामान्य रूप से, इसलिए कृपया, ऑपरेटिंग सिस्टम कार्यान्वयनकर्ता, मुझे इसके लिए लौ न दें) किसी अन्य प्रक्रिया को एक्सेस करने के लिए वर्चुअल मेमोरी, किसी प्रकार की मेमोरी अटैच सिस्टम कॉल न होना जो आपको अनुमति देता है पहुंच। वर्चुअल मेमोरी एड्रेस का मतलब आम तौर पर विचार की जाने वाली प्रक्रिया के आधार पर अलग-अलग चीजों से है।
लुइस कोलोराडो

38

एक विभाजन दोष एक पृष्ठ के लिए एक अनुरोध के कारण होता है जिसे प्रक्रिया ने अपने विवरण तालिका में सूचीबद्ध नहीं किया है, या उस पृष्ठ के लिए एक अमान्य अनुरोध जो इसे सूचीबद्ध किया है (उदाहरण के लिए केवल-पढ़ने के लिए एक लेखन अनुरोध)।

डैंगलिंग पॉइंटर एक ऐसा पॉइंटर होता है जो किसी वैध पेज की ओर इशारा करता है या नहीं कर सकता है, लेकिन यह मेमोरी के "अनपेक्षित" सेगमेंट को इंगित करता है।


10
यह सच है, लेकिन क्या यह वास्तव में आपकी मदद करेगा यदि आप पहले से ही नहीं जानते थे कि एक विभाजन दोष क्या है?
जूल

29

ईमानदार होने के लिए, जैसा कि अन्य पोस्टरों ने उल्लेख किया है, विकिपीडिया पर इस पर बहुत अच्छा लेख है इसलिए वहां एक नज़र डालें। इस तरह की त्रुटि बहुत आम है और अक्सर अन्य चीजें जैसे एक्सेस वॉयलेशन या सामान्य सुरक्षा दोष।

वे C, C ++ या किसी अन्य भाषा में भिन्न नहीं हैं जो संकेत देता है। इस प्रकार की त्रुटियां आमतौर पर पॉइंटर्स के कारण होती हैं

  1. प्रारंभिक रूप से आरंभ होने से पहले उपयोग किया जाता है
  2. मेमोरी के बाद उपयोग किया जाता है जिसे वे वास्तविक रूप से हटाए गए या हटाए गए हैं।
  3. एक अनुक्रमित सरणी में उपयोग किया जाता है जहां सूचकांक सरणी सीमा के बाहर होता है। यह आम तौर पर केवल तब होता है जब आप पारंपरिक सरणियों या सी-स्ट्रिंग्स पर सूचक गणित कर रहे होते हैं, न कि एसटीएल / बूस्ट आधारित संग्रह (सी ++ में)।

16

विकिपीडिया के अनुसार:

एक विभाजन दोष तब होता है जब कोई प्रोग्राम मेमोरी स्थान तक पहुंचने का प्रयास करता है जिसे उसे एक्सेस करने की अनुमति नहीं होती है, या मेमोरी स्थान तक पहुंचने का प्रयास इस तरह से किया जाता है कि अनुमति नहीं है (उदाहरण के लिए, केवल-पढ़ने के लिए लिखने का प्रयास करने के लिए, या ऑपरेटिंग सिस्टम का हिस्सा अधिलेखित करने के लिए)।


13

सेग्मेंटेशन फॉल्ट भी हार्डवेयर विफलताओं के कारण होता है, इस मामले में रैम की यादें। यह कम सामान्य कारण है, लेकिन अगर आपको अपने कोड में कोई त्रुटि नहीं मिलती है, तो शायद एक यादगार मदद कर सकता है।

इस मामले में समाधान, रैम को बदलें।

संपादित करें:

यहाँ एक संदर्भ है: हार्डवेयर द्वारा विभाजन दोष


3
दोषपूर्ण रैम के लिए एक त्वरित और गंदा परीक्षण आपके दुर्घटनाग्रस्त कार्यक्रम को बार-बार लूप में चलाना है। यदि प्रोग्राम में कोई आंतरिक nondeterminism नहीं है - अर्थात, यह हमेशा एक ही इनपुट के लिए एक ही आउटपुट का उत्पादन करता है, या कम से कम यह माना जाता है कि - लेकिन, कुछ विशेष इनपुट के लिए, यह कभी-कभी दुर्घटनाग्रस्त हो जाता है , हमेशा नहीं, लेकिन कभी भी नहीं: तो आपको चाहिए खराब रैम के बारे में चिंता करना शुरू करें।
२१

8

सेगमेंटेशन दोष तब होता है जब कोई प्रक्रिया (किसी प्रोग्राम का रनिंग इंस्टेंस) रीड-ओनली मेमोरी एड्रेस या मेमोरी रेंज तक पहुंचने की कोशिश कर रही होती है, जो अन्य प्रक्रिया द्वारा उपयोग की जा रही होती है या नॉन-एज़ेंट (अमान्य) मेमोरी एड्रेस को एक्सेस करती है। डैंगलिंग रेफरेंस (पॉइंटर) समस्या का मतलब है कि किसी ऐसी वस्तु या चर को एक्सेस करने की कोशिश करना, जिसकी सामग्री को पहले ही मेमोरी से हटा दिया गया हो, जैसे:

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here

4
किसी सरणी को हटाने का सही तरीका है हटाना [] गिरफ्तारी;
दामियन

8

विकिपीडिया के सेगमेंटेशन_फॉल्ट पेज में इसके बारे में बहुत अच्छा वर्णन है, बस इसके कारणों और कारणों की ओर संकेत किया गया है। विस्तृत विवरण के लिए विकी पर एक नज़र डालें।

कंप्यूटिंग में, एक विभाजन दोष (जिसे अक्सर segfault के लिए छोटा किया जाता है) या एक्सेस उल्लंघन एक मेमोरी एक्सेस उल्लंघन के बारे में ऑपरेटिंग सिस्टम (OS) को सूचित करते हुए, मेमोरी प्रोटेक्शन के साथ हार्डवेयर द्वारा उठाया गया एक दोष है।

एक विभाजन दोष के कुछ विशिष्ट कारण निम्नलिखित हैं:

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

बदले में ये अक्सर उन प्रोग्रामिंग त्रुटियों के कारण होते हैं जिनके परिणामस्वरूप अमान्य मेमोरी एक्सेस होती है:

  • एक अनइंस्टाल्यूटेड पॉइंटर (वाइल्ड पॉइंटर, जो एक रैंडम मेमोरी एड्रेस की ओर इशारा करता है) को डीफ्रेंसिंग या असाइन करना

  • मुक्त किए गए पॉइंटर (झूलने वाला पॉइंटर) को डीफ्रेंसिंग या असाइन करना, जो उस मेमोरी को इंगित करता है जिसे फ्रीज / डिलीट / डिलीट किया गया है)

  • एक बफर अतिप्रवाह।

  • एक ढेर अतिप्रवाह।

  • एक प्रोग्राम को निष्पादित करने का प्रयास करना जो सही ढंग से संकलित नहीं करता है। (कुछ संकलक संकलन-समय त्रुटियों की उपस्थिति के बावजूद एक निष्पादन योग्य फ़ाइल का उत्पादन करेंगे।)


6

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


3

"सेगमेंटेशन फ़ॉल्ट" का अर्थ है कि आपने उस मेमोरी को एक्सेस करने की कोशिश की है जिसकी आपके पास पहुँच नहीं है।

पहली समस्या मुख्य के आपके तर्कों के साथ है। मुख्य कार्य होना चाहिए int main(int argc, char *argv[]), और आपको यह देखना चाहिए कि argv तक पहुँचने से पहले argc कम से कम 2 है।

इसके अलावा, जब से आप एक फ्लोट में प्रिंटफ में जा रहे हैं (जो, वैसे, प्रिंटफ से गुजरते समय एक डबल में परिवर्तित हो जाता है), तो आपको% f प्रारूप विनिर्देशक का उपयोग करना चाहिए। % S प्रारूप विनिर्देशक तार के लिए है ('\ 0'-समाप्त वर्ण सरणियाँ)।


2

एक विभाजन दोष या पहुंच उल्लंघन तब होता है जब कोई प्रोग्राम स्मृति स्थान तक पहुंचने का प्रयास करता है जो मौजूद नहीं है, या किसी स्मृति स्थान तक पहुंचने की कोशिश नहीं करता है, जिसकी अनुमति नहीं है।

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

यहां मैं [1000] मौजूद नहीं है, इसलिए सेगफॉल्ट होता है।

विभाजन दोष के कारण:

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers  this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside processs address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).

2
सबसे पहले, एसईजी गलती का पता नहीं है या मौजूद नहीं है के साथ कुछ नहीं करना है। यह आपके बारे में है कि आप इसे एक्सेस कर रहे हैं जहां आपको ऐसा करने की अनुमति नहीं है। और आपके विशेष उदाहरण में यह मानक के अनुसार भी है कि स्थान मौजूद है। चूँकि मानक एरे केस में कहते हैं कि यह दिया जाना चाहिए कि इसके बाउंड और 1 के भीतर एक अच्छी तरह से संरेखित सरणी पर एक पॉइंटर पॉइंट के लिए एक वैध पता है ।
dhein

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

2

"विभाजन गलती" जवाब में के कई अच्छा स्पष्टीकरण हैं, लेकिन विभाजन गलती के साथ के बाद से अक्सर वहाँ स्मृति सामग्री की एक डंप है, मैं जहां के बीच के रिश्ते भाग में "कोर फेंक दिया" साझा करना चाहते थे विभाजन गलती (कोर फेंक दिया) और स्मृति से आता है:

लगभग 1955 से 1975 तक - सेमीकंडक्टर मेमोरी से पहले - कंप्यूटर मेमोरी में प्रमुख प्रौद्योगिकी तांबे के तारों पर टंगे छोटे चुंबकीय डोनट्स का उपयोग करती थी। डोनट्स को "फेराइट कोर" और मुख्य मेमोरी के रूप में जाना जाता था, जिसे "कोर मेमोरी" या "कोर" के रूप में जाना जाता था।

यहां से ले गए ।


2

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

  1. आप प्रिंटफ़ में argumet प्रकार के बेमेल होने पर नीचे के मामले में विभाजन की गलती पा सकते हैं

    #include<stdio.h> int main(){
    int a = 5; printf("%s",a); return 0; }

आउटपुट: Segmentation Fault (SIGSEGV)

  1. जब आप एक पॉइंटर को मेमोरी आवंटित करना भूल जाते हैं, लेकिन इसका उपयोग करने की कोशिश कर रहे हैं।

     #include<stdio.h> 
     typedef struct{
       int a;
     }myStruct;   
    int main(){
      myStruct *s;
      /* few lines of code */
      s->a = 5;
      return 0;
    }

आउटपुट: Segmentation Fault (SIGSEGV)


1

Segmentation faultइसका सीधा सा अर्थ यह है कि आप कुछ ऐसी स्मृति तक पहुँचने की कोशिश कर रहे हैं, जो आपकी नहीं है। Segmentation faultतब होता है जब हम पढ़ने और / या पढ़ने के कार्यों को केवल मेमोरी लोकेशन में लिखने का प्रयास करते हैं या मुक्त मेमोरी की कोशिश करते हैं। दूसरे शब्दों में, हम इसे किसी प्रकार के स्मृति भ्रष्टाचार के रूप में समझा सकते हैं।

नीचे मैं प्रोग्रामर द्वारा की जाने वाली सामान्य गलतियों का उल्लेख करता हूं जो आगे बढ़ती हैं Segmentation fault

  • scanf()गलत तरीके से उपयोग करना (डाल देना भूल गया &)।
int num;
scanf("%d", num);// must use &num instead of num
  • गलत तरीके से पॉइंटर्स का उपयोग करें।
int *num; 
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
  • एक स्ट्रिंग शाब्दिक रूप से संशोधित करना (सूचक केवल पढ़ने के लिए मेमोरी को लिखने या संशोधित करने का प्रयास करता है।)
char *str;  

//Stored in read only part of data segment
str = "GfG";      

//Problem:  trying to modify read only memory
*(str+1) = 'n';
  • एक पते के माध्यम से पहुंचने की कोशिश करें जो पहले से ही मुक्त है।
// allocating memory to num 
int* num = malloc(8); 
*num = 100; 

// de-allocated the space allocated to num 
free(num); 

// num is already freed there for it cause segmentation fault
*num = 110; 
  • स्टैक ओवरफ्लो -: स्टैक पर मेमोरी से बाहर चल रहा है
  • किसी सरणी को सीमा से बाहर करना '
  • का उपयोग करते समय गलत प्रारूप विनिर्देशक का उपयोग करें printf()और scanf()'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.