विभाजन दोष (सेगमेंटेशन फॉल्ट): Difference between revisions
No edit summary |
No edit summary |
||
Line 4: | Line 4: | ||
वेबसाइट|सेगफॉल्ट (वेबसाइट)}} | वेबसाइट|सेगफॉल्ट (वेबसाइट)}} | ||
[[ कम्प्यूटिंग ]]में, विभाजन दोष या एक्सेस उल्लंघन [[दोष (कंप्यूटिंग)]], या विफलता की स्थिति है, जो मेमोरी सुरक्षा के साथ हार्डवेयर द्वारा उठाया जाता है, [[ऑपरेटिंग सिस्टम]] (OS) को सूचित करता है, सॉफ्टवेयर ने प्रतिबंधित क्षेत्र तक पहुंचने का प्रयास किया है। मेमोरी ( | [[ कम्प्यूटिंग ]]में, विभाजन दोष या एक्सेस उल्लंघन [[दोष (कंप्यूटिंग)]], या विफलता की स्थिति है, जो मेमोरी सुरक्षा के साथ हार्डवेयर द्वारा उठाया जाता है, [[ऑपरेटिंग सिस्टम|ऑपरेटिंग प्रणाली]] (OS) को सूचित करता है, सॉफ्टवेयर ने प्रतिबंधित क्षेत्र तक पहुंचने का प्रयास किया है। मेमोरी ( मेमोरी एक्सेस उल्लंघन) मानक x[[86]] कंप्यूटरों पर, यह सामान्य सुरक्षा दोष का रूप है। [[ऑपरेटिंग सिस्टम कर्नेल|ऑपरेटिंग प्रणाली कर्नेल]], प्रतिक्रिया में, सामान्यतः कुछ सुधारात्मक कार्रवाई करता है, सामान्यतः प्रक्रिया को [[ संकेत (कंप्यूटिंग) ]] भेजकर त्रुटि को आपत्तिजनक [[प्रक्रिया (कंप्यूटिंग)]] पर भेज देता है। प्रक्रियाएं कुछ स्थितियों में कस्टम सिग्नल हैंडलर स्थापित कर सकती हैं, जिससे उन्हें स्वयं ठीक होने की अनुमति मिलती है,<ref name="Peter Van der Linden">''Expert C programming: deep C secrets'' By Peter Van der Linden, page 188</ref> अन्यथा ओएस डिफ़ॉल्ट सिग्नल हैंडलर का उपयोग किया जाता है, सामान्यतः प्रक्रिया की [[असामान्य समाप्ति]] (प्रोग्राम [[क्रैश (कंप्यूटिंग)]]), और कभी-कभी [[कोर निपात]] होता है। | ||
सेगमेंटेशन दोष [[सी (प्रोग्रामिंग भाषा)]] जैसी भाषाओं में लिखे गए प्रोग्रामों में त्रुटि का एक सामान्य वर्ग है जो निम्न-स्तरीय मेमोरी एक्सेस प्रदान करता है और कुछ से लेकर कोई सुरक्षा जांच नहीं करता है। वे मुख्य रूप से [[ आभासी मेमोरी ]] एड्रेसिंग के लिए पॉइंटर (कंप्यूटर प्रोग्रामिंग) के उपयोग में त्रुटियों के कारण उत्पन्न होते हैं, विशेष रूप से अवैध पहुंच के कारण। एक अन्य प्रकार की मेमोरी एक्सेस त्रुटि एक [[बस त्रुटि]] है, जिसके विभिन्न कारण भी हैं, | सेगमेंटेशन दोष [[सी (प्रोग्रामिंग भाषा)]] जैसी भाषाओं में लिखे गए प्रोग्रामों में त्रुटि का एक सामान्य वर्ग है जो निम्न-स्तरीय मेमोरी एक्सेस प्रदान करता है और कुछ से लेकर कोई सुरक्षा जांच नहीं करता है। वे मुख्य रूप से [[ आभासी मेमोरी ]] एड्रेसिंग के लिए पॉइंटर (कंप्यूटर प्रोग्रामिंग) के उपयोग में त्रुटियों के कारण उत्पन्न होते हैं, विशेष रूप से अवैध पहुंच के कारण। एक अन्य प्रकार की मेमोरी एक्सेस त्रुटि एक [[बस त्रुटि]] है, जिसके विभिन्न कारण भी हैं, किन्तु आज यह बहुत दुर्लभ है; ये मुख्य रूप से गलत भौतिक मेमोरी एड्रेसिंग के कारण होते हैं, या गलत तरीके से मेमोरी एक्सेस के कारण होते हैं - ये ऐसे मेमोरी रेफरेंस होते हैं जिन्हें हार्डवेयर एड्रेस नहीं कर सकता है, बजाय उन रेफरेंस के जिन्हें एड्रेस करने की अनुमति नहीं है। | ||
कई प्रोग्रामिंग लैंग्वेज सेगमेंटेशन दोषों से बचने और मेमोरी सुरक्षा में सुधार के लिए डिज़ाइन किए गए तंत्रों को नियोजित कर सकती हैं। उदाहरण के लिए, [[ जंग (प्रोग्रामिंग भाषा) ]] एक स्वामित्व-आधारित को नियोजित करता है<ref>{{cite web| url = http://doc.rust-lang.org/book/ownership.html| title = The Rust Programming Language - Ownership}}</ref> स्मृति सुरक्षा सुनिश्चित करने के लिए मॉडल।<ref>{{cite web| url = http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html| title = Fearless Concurrency with Rust - The Rust Programming Language Blog}}</ref> अन्य भाषाएँ, जैसे कि [[लिस्प (प्रोग्रामिंग भाषा)]] और [[जावा (प्रोग्रामिंग भाषा)]], [[कचरा संग्रह (कंप्यूटर विज्ञान)]] को नियोजित करती हैं,<ref>{{Cite journal|url=http://www-formal.stanford.edu/jmc/recursive.html|title=सांकेतिक भावों के पुनरावर्ती कार्य और मशीन द्वारा उनकी गणना, भाग I|last=McCarthy|first=John|author-link=John McCarthy (computer scientist)|date=April 1960|journal=[[Communications of the ACM]]|volume=4|issue=3|pages=184–195|doi=10.1145/367177.367199|s2cid=1489409|access-date=2018-09-22|doi-access=free}}</ref> जो स्मृति त्रुटियों के कुछ वर्गों से बचा जाता है जिससे विभाजन दोष हो सकते हैं।<ref>{{cite journal|last1=Dhurjati|first1=Dinakar|last2=Kowshik|first2=Sumant|last3=Adve|first3=Vikram|last4=Lattner|first4=Chris|title=मेमोरी सुरक्षा रनटाइम चेक या कचरा संग्रह के बिना|journal=Proceedings of the 2003 ACM SIGPLAN Conference on Language, Compiler, and Tool for Embedded Systems|date=1 January 2003|volume=38|issue=7|pages=69–80|doi=10.1145/780732.780743|url=http://llvm.org/pubs/2003-05-05-LCTES03-CodeSafety.pdf|access-date=2018-09-22|publisher=ACM|language=en|isbn=1581136471|s2cid=1459540}}</ref> | कई प्रोग्रामिंग लैंग्वेज सेगमेंटेशन दोषों से बचने और मेमोरी सुरक्षा में सुधार के लिए डिज़ाइन किए गए तंत्रों को नियोजित कर सकती हैं। उदाहरण के लिए, [[ जंग (प्रोग्रामिंग भाषा) ]] एक स्वामित्व-आधारित को नियोजित करता है<ref>{{cite web| url = http://doc.rust-lang.org/book/ownership.html| title = The Rust Programming Language - Ownership}}</ref> स्मृति सुरक्षा सुनिश्चित करने के लिए मॉडल।<ref>{{cite web| url = http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html| title = Fearless Concurrency with Rust - The Rust Programming Language Blog}}</ref> अन्य भाषाएँ, जैसे कि [[लिस्प (प्रोग्रामिंग भाषा)]] और [[जावा (प्रोग्रामिंग भाषा)]], [[कचरा संग्रह (कंप्यूटर विज्ञान)]] को नियोजित करती हैं,<ref>{{Cite journal|url=http://www-formal.stanford.edu/jmc/recursive.html|title=सांकेतिक भावों के पुनरावर्ती कार्य और मशीन द्वारा उनकी गणना, भाग I|last=McCarthy|first=John|author-link=John McCarthy (computer scientist)|date=April 1960|journal=[[Communications of the ACM]]|volume=4|issue=3|pages=184–195|doi=10.1145/367177.367199|s2cid=1489409|access-date=2018-09-22|doi-access=free}}</ref> जो स्मृति त्रुटियों के कुछ वर्गों से बचा जाता है जिससे विभाजन दोष हो सकते हैं।<ref>{{cite journal|last1=Dhurjati|first1=Dinakar|last2=Kowshik|first2=Sumant|last3=Adve|first3=Vikram|last4=Lattner|first4=Chris|title=मेमोरी सुरक्षा रनटाइम चेक या कचरा संग्रह के बिना|journal=Proceedings of the 2003 ACM SIGPLAN Conference on Language, Compiler, and Tool for Embedded Systems|date=1 January 2003|volume=38|issue=7|pages=69–80|doi=10.1145/780732.780743|url=http://llvm.org/pubs/2003-05-05-LCTES03-CodeSafety.pdf|access-date=2018-09-22|publisher=ACM|language=en|isbn=1581136471|s2cid=1459540}}</ref> | ||
Line 14: | Line 14: | ||
[[File:FreeBSD kernel panic.png|thumb|मानव जनित सिग्नल का उदाहरण]] | [[File:FreeBSD kernel panic.png|thumb|मानव जनित सिग्नल का उदाहरण]] | ||
[[File:KDE Crash Handler screenshot.png|thumb|[[ कहाँ ]] डेस्कटॉप वातावरण में विभाजन दोष [[ गिरा ]] को प्रभावित कर रहा है]] | [[File:KDE Crash Handler screenshot.png|thumb|[[ कहाँ ]] डेस्कटॉप वातावरण में विभाजन दोष [[ गिरा ]] को प्रभावित कर रहा है]] | ||
[[File:Windows null ptr dereference.png|thumb|[[विंडोज 8]] पर एक [[नल पॉइंटर]] [[डेरेफरेंस ऑपरेटर]]]]सेगमेंटेशन फॉल्ट तब होता है जब कोई प्रोग्राम [[स्मृति]] लोकेशन तक पहुंचने का प्रयास करता है जिसे एक्सेस करने की अनुमति नहीं है, या किसी मेमोरी लोकेशन को इस तरह एक्सेस करने का प्रयास करता है जिसकी अनुमति नहीं है (उदाहरण के लिए, [[ केवल पढ़ने के लिये मेमोरी ]] में लिखने का प्रयास | रीड-ओनली लोकेशन, या ऑपरेटिंग | [[File:Windows null ptr dereference.png|thumb|[[विंडोज 8]] पर एक [[नल पॉइंटर]] [[डेरेफरेंस ऑपरेटर]]]]सेगमेंटेशन फॉल्ट तब होता है जब कोई प्रोग्राम [[स्मृति]] लोकेशन तक पहुंचने का प्रयास करता है जिसे एक्सेस करने की अनुमति नहीं है, या किसी मेमोरी लोकेशन को इस तरह एक्सेस करने का प्रयास करता है जिसकी अनुमति नहीं है (उदाहरण के लिए, [[ केवल पढ़ने के लिये मेमोरी ]] में लिखने का प्रयास | रीड-ओनली लोकेशन, या ऑपरेटिंग प्रणाली के हिस्से को ओवरराइट करने के लिए)। | ||
शब्द विभाजन के कंप्यूटिंग में विभिन्न उपयोग हैं; सेगमेंटेशन फॉल्ट के संदर्भ में, 1950 के दशक से इस्तेमाल किया जाने वाला शब्द,{{cn|date=February 2021}} यह किसी प्रोग्राम के एड्रेस स्पेस को संदर्भित करता है।<ref>{{Cite web|title=डिबगिंग विभाजन दोष और सूचक समस्याएं - Cprogramming.com|url=https://www.cprogramming.com/debugging/segfaults.html|access-date=2021-02-03|website=www.cprogramming.com}}</ref> स्मृति सुरक्षा के साथ, केवल प्रोग्राम का अपना पता स्थान ही पढ़ने योग्य होता है, और इसमें से केवल [[कॉल स्टैक]] और प्रोग्राम के डेटा सेगमेंट का रीड/राइट भाग लिखने योग्य होता है, जबकि रीड-ओनली डेटा और [[ कोड खंड ]] लिखने योग्य नहीं होते हैं। इस प्रकार प्रोग्राम के एड्रेस स्पेस के बाहर पढ़ने का प्रयास, या एड्रेस स्पेस के रीड-ओनली सेगमेंट में लिखने से सेगमेंटेशन फॉल्ट होता है, इसलिए नाम। | शब्द विभाजन के कंप्यूटिंग में विभिन्न उपयोग हैं; सेगमेंटेशन फॉल्ट के संदर्भ में, 1950 के दशक से इस्तेमाल किया जाने वाला शब्द,{{cn|date=February 2021}} यह किसी प्रोग्राम के एड्रेस स्पेस को संदर्भित करता है।<ref>{{Cite web|title=डिबगिंग विभाजन दोष और सूचक समस्याएं - Cprogramming.com|url=https://www.cprogramming.com/debugging/segfaults.html|access-date=2021-02-03|website=www.cprogramming.com}}</ref> स्मृति सुरक्षा के साथ, केवल प्रोग्राम का अपना पता स्थान ही पढ़ने योग्य होता है, और इसमें से केवल [[कॉल स्टैक]] और प्रोग्राम के डेटा सेगमेंट का रीड/राइट भाग लिखने योग्य होता है, जबकि रीड-ओनली डेटा और [[ कोड खंड ]] लिखने योग्य नहीं होते हैं। इस प्रकार प्रोग्राम के एड्रेस स्पेस के बाहर पढ़ने का प्रयास, या एड्रेस स्पेस के रीड-ओनली सेगमेंट में लिखने से सेगमेंटेशन फॉल्ट होता है, इसलिए नाम। | ||
वर्चुअल मेमोरी प्रदान करने के लिए हार्डवेयर [[ स्मृति विभाजन ]] का उपयोग करने वाले | वर्चुअल मेमोरी प्रदान करने के लिए हार्डवेयर [[ स्मृति विभाजन ]] का उपयोग करने वाले प्रणाली पर, सेगमेंटेशन त्रुटि तब होती है जब हार्डवेयर गैर-मौजूद सेगमेंट को संदर्भित करने का प्रयास करता है, [[डेटा खंड]] की सीमाओं के बाहर किसी स्थान को संदर्भित करता है, या किसी स्थान को संदर्भित करता है। उस सेगमेंट के लिए दी गई अनुमतियों द्वारा अनुमत फैशन नहीं। केवल [[पेजिंग]] का उपयोग करने वाले प्रणाली पर, एक [[अमान्य पृष्ठ दोष]] सामान्यतः एक विभाजन दोष की ओर जाता है, और विभाजन दोष और पृष्ठ दोष दोनों ही वर्चुअल मेमोरी मैनेजमेंट प्रणाली द्वारा उठाए गए दोष हैं। सेगमेंटेशन दोष पृष्ठ दोषों से स्वतंत्र रूप से भी हो सकते हैं: वैध पृष्ठ तक अवैध पहुंच एक सेगमेंटेशन त्रुटि है, किन्तु अमान्य पृष्ठ त्रुटि नहीं है, और सेगमेंटेशन दोष पृष्ठ के मध्य में हो सकते हैं (इसलिए कोई पृष्ठ त्रुटि नहीं है), उदाहरण के लिए [[ बफ़र अधिकता ]] जो एक पृष्ठ के भीतर रहता है किन्तु अवैध रूप से स्मृति को अधिलेखित कर देता है। | ||
हार्डवेयर स्तर पर, [[स्मृति प्रबंधन इकाई]] (एमएमयू) द्वारा अवैध पहुंच (यदि संदर्भित मेमोरी मौजूद है) द्वारा इसकी स्मृति सुरक्षा सुविधा के भाग के रूप में, या एक अमान्य पृष्ठ दोष (यदि संदर्भित स्मृति मौजूद नहीं है) द्वारा शुरू में | हार्डवेयर स्तर पर, [[स्मृति प्रबंधन इकाई]] (एमएमयू) द्वारा अवैध पहुंच (यदि संदर्भित मेमोरी मौजूद है) द्वारा इसकी स्मृति सुरक्षा सुविधा के भाग के रूप में, या एक अमान्य पृष्ठ दोष (यदि संदर्भित स्मृति मौजूद नहीं है) द्वारा शुरू में त्रुटि उठाई जाती है ). यदि समस्या एक अमान्य तार्किक पता नहीं है बल्कि एक अमान्य भौतिक पता है, तो इसके बजाय एक बस त्रुटि उठाई जाती है, हालांकि ये हमेशा अलग नहीं होते हैं। | ||
ऑपरेटिंग | ऑपरेटिंग प्रणाली के स्तर पर, यह त्रुटि पकड़ी जाती है और उस सिग्नल के लिए प्रक्रिया के हैंडलर को सक्रिय करते हुए, आपत्तिजनक प्रक्रिया को एक संकेत दिया जाता है। अलग-अलग ऑपरेटिंग प्रणाली में अलग-अलग सिग्नल नाम होते हैं जो इंगित करते हैं कि सेगमेंटेशन त्रुटि हुई है। यूनिक्स जैसे ऑपरेटिंग प्रणाली पर, SIGSEGV नामक एक सिग्नल (विभाजन उल्लंघन से संक्षिप्त) को आपत्तिजनक प्रक्रिया के लिए भेजा जाता है। [[Microsoft Windows]] पर, आपत्तिजनक प्रक्रिया को एक STATUS_ACCESS_VIOLATION अपवाद प्रबंधन प्राप्त होता है। | ||
== कारण == | == कारण == | ||
जिन परिस्थितियों में सेगमेंटेशन का उल्लंघन होता है और वे खुद को कैसे प्रकट करते हैं, वे हार्डवेयर और ऑपरेटिंग | जिन परिस्थितियों में सेगमेंटेशन का उल्लंघन होता है और वे खुद को कैसे प्रकट करते हैं, वे हार्डवेयर और ऑपरेटिंग प्रणाली के लिए विशिष्ट हैं: अलग-अलग हार्डवेयर दी गई शर्तों के लिए अलग-अलग दोष पैदा करते हैं, और अलग-अलग ऑपरेटिंग प्रणाली इन्हें अलग-अलग सिग्नल में परिवर्तित करते हैं जो प्रक्रियाओं पर पारित होते हैं। निकटस्थ कारण एक मेमोरी एक्सेस उल्लंघन है, जबकि अंतर्निहित कारण सामान्यतः किसी प्रकार का [[सॉफ्टवेयर बग]] है। [[मूल कारण विश्लेषण]] का निर्धारण - बग को डिबग करना - कुछ मामलों में सरल हो सकता है, जहां प्रोग्राम लगातार सेगमेंटेशन त्रुटि का कारण बनता है (उदाहरण के लिए, शून्य सूचक को संदर्भित करना), जबकि अन्य मामलों में बग को पुन: पेश करना और स्मृति पर निर्भर करना मुश्किल हो सकता है प्रत्येक रन पर आवंटन (उदाहरण के लिए, झूलने वाले सूचक को संदर्भित करना)। | ||
विभाजन दोष के कुछ विशिष्ट कारण निम्नलिखित हैं: | विभाजन दोष के कुछ विशिष्ट कारण निम्नलिखित हैं: | ||
Line 32: | Line 32: | ||
* रीड-ओनली मेमोरी (जैसे कोड सेगमेंट) लिखने का प्रयास | * रीड-ओनली मेमोरी (जैसे कोड सेगमेंट) लिखने का प्रयास | ||
ये बदले में प्रायः प्रोग्रामिंग त्रुटियों के कारण होते हैं, जिसके परिणामस्वरूप अमान्य मेमोरी एक्सेस होती है: | ये बदले में प्रायः प्रोग्रामिंग त्रुटियों के कारण होते हैं, जिसके परिणामस्वरूप अमान्य मेमोरी एक्सेस होती है: | ||
* एक अशक्त सूचक को संदर्भित करना, जो | * एक अशक्त सूचक को संदर्भित करना, जो सामान्यतः एक ऐसे पते की ओर इशारा करता है जो प्रक्रिया के पता स्थान का हिस्सा नहीं है | ||
* एक गैर-प्रारंभिक सूचक ([[जंगली सूचक]], जो एक यादृच्छिक स्मृति पते को इंगित करता है) को संदर्भित या असाइन करना | * एक गैर-प्रारंभिक सूचक ([[जंगली सूचक]], जो एक यादृच्छिक स्मृति पते को इंगित करता है) को संदर्भित या असाइन करना | ||
* फ्रीड पॉइंटर को डिफ्रेंसिंग या असाइन करना (झूलने वाला पॉइंटर, जो उस मेमोरी को इंगित करता है जिसे मुक्त/डीललोकेटेड/डिलीट किया गया है) | * फ्रीड पॉइंटर को डिफ्रेंसिंग या असाइन करना (झूलने वाला पॉइंटर, जो उस मेमोरी को इंगित करता है जिसे मुक्त/डीललोकेटेड/डिलीट किया गया है) | ||
Line 39: | Line 39: | ||
* ऐसे प्रोग्राम को निष्पादित करने का प्रयास करना जो सही ढंग से संकलित नहीं होता है। (कुछ संकलक{{Which?|date=December 2021}} संकलन-समय त्रुटियों की उपस्थिति के बावजूद निष्पादन योग्य फ़ाइल आउटपुट करेगा।) | * ऐसे प्रोग्राम को निष्पादित करने का प्रयास करना जो सही ढंग से संकलित नहीं होता है। (कुछ संकलक{{Which?|date=December 2021}} संकलन-समय त्रुटियों की उपस्थिति के बावजूद निष्पादन योग्य फ़ाइल आउटपुट करेगा।) | ||
सी कोड में, सेगमेंटेशन दोष प्रायः पॉइंटर उपयोग में त्रुटियों के कारण होते हैं, खासकर [[सी गतिशील स्मृति आवंटन]] में। अशक्त सूचक को संदर्भित करना, जिसके परिणामस्वरूप [[अपरिभाषित व्यवहार]] होता है, | सी कोड में, सेगमेंटेशन दोष प्रायः पॉइंटर उपयोग में त्रुटियों के कारण होते हैं, खासकर [[सी गतिशील स्मृति आवंटन]] में। अशक्त सूचक को संदर्भित करना, जिसके परिणामस्वरूप [[अपरिभाषित व्यवहार]] होता है, सामान्यतः एक विभाजन दोष का कारण होगा। ऐसा इसलिए है क्योंकि एक शून्य सूचक वैध स्मृति पता नहीं हो सकता है। दूसरी ओर, वाइल्ड पॉइंटर्स और डैंगलिंग पॉइंटर्स उस मेमोरी की ओर इशारा करते हैं जो मौजूद हो भी सकती है और नहीं भी, और पढ़ने योग्य या लिखने योग्य हो भी सकती है और नहीं भी, और इस प्रकार क्षणिक बग का परिणाम हो सकता है। उदाहरण के लिए: | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
char *p1 = NULL; // Null pointer | char *p1 = NULL; // Null pointer | ||
Line 47: | Line 47: | ||
free(p3); // p3 is now a dangling pointer, as memory has been freed | free(p3); // p3 is now a dangling pointer, as memory has been freed | ||
</syntaxhighlight> | </syntaxhighlight> | ||
इनमें से किसी भी वेरिएबल को डिफ्रेंस करने से सेगमेंटेशन फॉल्ट हो सकता है: नल पॉइंटर को डीरेफर करने से | इनमें से किसी भी वेरिएबल को डिफ्रेंस करने से सेगमेंटेशन फॉल्ट हो सकता है: नल पॉइंटर को डीरेफर करने से सामान्यतः एक सेगफॉल्ट होता है, जबकि वाइल्ड पॉइंटर से पढ़ने के बजाय रैंडम डेटा हो सकता है, किन्तु कोई सेगफॉल्ट नहीं होता है, और डैंगलिंग पॉइंटर से पढ़ने के परिणामस्वरूप वैध डेटा हो सकता है। जबकि, और फिर यादृच्छिक डेटा, क्योंकि यह ओवरराइट किया गया है। | ||
== हैंडलिंग == | == हैंडलिंग == | ||
सेगमेंटेशन | सेगमेंटेशन त्रुटि या बस त्रुटि के लिए डिफ़ॉल्ट क्रिया उस प्रक्रिया की असामान्य समाप्ति है जिसने इसे ट्रिगर किया। डिबगिंग में सहायता के लिए एक [[कोर फ़ाइल]] उत्पन्न की जा सकती है, और अन्य प्लेटफ़ॉर्म-निर्भर क्रियाएं भी की जा सकती हैं। उदाहरण के लिए, ग्रसिक्युरिटी पैच का उपयोग करने वाले [[लिनक्स]] प्रणाली बफर ओवरफ्लो का उपयोग करके संभावित घुसपैठ के प्रयासों की निगरानी के लिए SIGSEGV संकेतों को लॉग कर सकते हैं। | ||
कुछ प्रणालियों पर, जैसे कि लिनक्स और विंडोज, यह संभव है कि कार्यक्रम स्वयं एक विभाजन दोष को संभाले।<ref>{{Cite web|url=https://feepingcreature.github.io/handling.html|title=Cleanly recovering from Segfaults under Windows and Linux (32-bit, x86)|access-date=2020-08-23}}</ref> आर्किटेक्चर और ऑपरेटिंग | कुछ प्रणालियों पर, जैसे कि लिनक्स और विंडोज, यह संभव है कि कार्यक्रम स्वयं एक विभाजन दोष को संभाले।<ref>{{Cite web|url=https://feepingcreature.github.io/handling.html|title=Cleanly recovering from Segfaults under Windows and Linux (32-bit, x86)|access-date=2020-08-23}}</ref> आर्किटेक्चर और ऑपरेटिंग प्रणाली के आधार पर, रनिंग प्रोग्राम न केवल ईवेंट को हैंडल कर सकता है, बल्कि इसकी स्थिति के बारे में कुछ जानकारी निकाल सकता है जैसे [[स्टैक ट्रेस]] प्राप्त करना, [[प्रोसेसर रजिस्टर]] वैल्यू, स्रोत कोड की लाइन जब इसे ट्रिगर किया गया था, मेमोरी एड्रेस जो था अमान्य रूप से एक्सेस किया गया<ref>{{Cite web|url=https://github.com/vmarkovtsev/DeathHandler|title=Implementation of the SIGSEGV/SIGABRT handler which prints the debug stack trace.|website=[[GitHub]]|access-date=2020-08-23}}</ref> और क्या कार्रवाई पढ़ी गई या लिखी गई थी।<ref>{{Cite web|url=https://stackoverflow.com/questions/17671869/how-to-identify-read-or-write-operations-of-page-fault-when-using-sigaction-hand|title=How to identify read or write operations of page fault when using sigaction handler on SIGSEGV?(LINUX)|access-date=2020-08-23}}</ref> | ||
हालांकि एक सेगमेंटेशन | हालांकि एक सेगमेंटेशन त्रुटि का सामान्यतः मतलब है कि प्रोग्राम में एक बग है जिसे ठीक करने की आवश्यकता है, जानबूझकर ऐसी विफलता का कारण परीक्षण, डिबगिंग और प्लेटफॉर्म का अनुकरण करना भी संभव है जहां मेमोरी तक सीधी पहुंच की आवश्यकता है। बाद वाले मामले में, प्रणाली को त्रुटि होने के बाद भी प्रोग्राम को चलाने की अनुमति देने में सक्षम होना चाहिए। इस मामले में, जब प्रणाली अनुमति देता है, तो घटना को संभालना और निष्पादन जारी रखने के लिए असफल निर्देश पर कूदने के लिए प्रोसेसर प्रोग्राम काउंटर को बढ़ाना संभव है।<ref>{{Cite web|url=https://devarea.com/linux-writing-fault-handlers/|title=LINUX – WRITING FAULT HANDLERS|access-date=2020-08-23}}</ref> | ||
Line 63: | Line 63: | ||
रीड-ओनली मेमोरी में लिखने से सेगमेंटेशन फॉल्ट होता है। कोड त्रुटियों के स्तर पर, यह तब होता है जब प्रोग्राम अपने स्वयं के कोड सेगमेंट या डेटा सेगमेंट के रीड-ओनली हिस्से को लिखता है, क्योंकि ये OS द्वारा रीड-ओनली मेमोरी में लोड किए जाते हैं। | रीड-ओनली मेमोरी में लिखने से सेगमेंटेशन फॉल्ट होता है। कोड त्रुटियों के स्तर पर, यह तब होता है जब प्रोग्राम अपने स्वयं के कोड सेगमेंट या डेटा सेगमेंट के रीड-ओनली हिस्से को लिखता है, क्योंकि ये OS द्वारा रीड-ओनली मेमोरी में लोड किए जाते हैं। | ||
यहां [[एएनएसआई सी]] कोड का एक उदाहरण दिया गया है जो | यहां [[एएनएसआई सी]] कोड का एक उदाहरण दिया गया है जो सामान्यतः स्मृति सुरक्षा वाले प्लेटफॉर्म पर सेगमेंटेशन त्रुटि का कारण बनता है। यह एक स्ट्रिंग शाब्दिक को संशोधित करने का प्रयास करता है, जो एएनएसआई सी मानक के अनुसार अपरिभाषित व्यवहार है। अधिकांश [[ संकलक ]] इसे संकलित समय पर नहीं पकड़ेंगे, और इसके बजाय इसे निष्पादन योग्य कोड में संकलित करेंगे जो क्रैश हो जाएगा: | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
Line 72: | Line 72: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
जब इस कोड वाले प्रोग्राम को संकलित किया जाता है, तो स्ट्रिंग हैलो वर्ल्ड को प्रोग्राम एक्जीक्यूटेबल फ़ाइल के रोडाटा सेक्शन में रखा जाता है: डेटा सेगमेंट का रीड-ओनली सेक्शन। जब लोड किया जाता है, तो ऑपरेटिंग | जब इस कोड वाले प्रोग्राम को संकलित किया जाता है, तो स्ट्रिंग हैलो वर्ल्ड को प्रोग्राम एक्जीक्यूटेबल फ़ाइल के रोडाटा सेक्शन में रखा जाता है: डेटा सेगमेंट का रीड-ओनली सेक्शन। जब लोड किया जाता है, तो ऑपरेटिंग प्रणाली इसे अन्य स्ट्रिंग्स और निरंतर (प्रोग्रामिंग) डेटा के साथ मेमोरी के रीड-ओनली सेगमेंट में रखता है। जब निष्पादित किया जाता है, तो एक चर, s, स्ट्रिंग के स्थान को इंगित करने के लिए सेट किया जाता है, और चर के माध्यम से स्मृति में H वर्ण लिखने का प्रयास किया जाता है, जिससे विभाजन दोष उत्पन्न होता है। ऐसे प्रोग्राम को एक कंपाइलर के साथ संकलित करना जो संकलन समय पर केवल-पढ़ने के लिए स्थानों के असाइनमेंट की जांच नहीं करता है, और इसे यूनिक्स-जैसे ऑपरेटिंग प्रणाली पर चलाने से निम्न [[रनटाइम त्रुटि]] उत्पन्न होती है: | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
Line 91: | Line 91: | ||
s[0] = 'H'; // equivalently, *s = 'H'; | s[0] = 'H'; // equivalently, *s = 'H'; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
भले ही स्ट्रिंग अक्षर को संशोधित नहीं किया जाना चाहिए (यह सी मानक में अपरिभाषित व्यवहार है), सी में वे हैं <code>static char []</code> प्रकार,<ref>{{cite book|title=ISO/IEC 9899:1990 - Programming languages -- C|section=6.1.4 String literals}}</ref><ref>{{cite book|title=ISO/IEC 9899:1999 - Programming languages -- C|section=6.4.5 String literals}}</ref><ref>{{cite book|title=ISO/IEC 9899:2011 - Programming languages -- C|section=6.4.5 String literals|url=http://www.iso-9899.info/n1570.html#6.4.5p6}}</ref> इसलिए मूल कोड में कोई निहित रूपांतरण नहीं है (जो इंगित करता है a <code>char *</code> उस सरणी में), जबकि सी ++ में वे हैं <code>static const char []</code> प्रकार, और इस प्रकार एक निहित रूपांतरण होता है, इसलिए संकलक | भले ही स्ट्रिंग अक्षर को संशोधित नहीं किया जाना चाहिए (यह सी मानक में अपरिभाषित व्यवहार है), सी में वे हैं <code>static char []</code> प्रकार,<ref>{{cite book|title=ISO/IEC 9899:1990 - Programming languages -- C|section=6.1.4 String literals}}</ref><ref>{{cite book|title=ISO/IEC 9899:1999 - Programming languages -- C|section=6.4.5 String literals}}</ref><ref>{{cite book|title=ISO/IEC 9899:2011 - Programming languages -- C|section=6.4.5 String literals|url=http://www.iso-9899.info/n1570.html#6.4.5p6}}</ref> इसलिए मूल कोड में कोई निहित रूपांतरण नहीं है (जो इंगित करता है a <code>char *</code> उस सरणी में), जबकि सी ++ में वे हैं <code>static const char []</code> प्रकार, और इस प्रकार एक निहित रूपांतरण होता है, इसलिए संकलक सामान्यतः इस विशेष त्रुटि को पकड़ लेंगे। | ||
=== अशक्त सूचक dereference === | === अशक्त सूचक dereference === | ||
सी और सी-जैसी भाषाओं में, अशक्त संकेतकों का उपयोग बिना किसी वस्तु के संकेतक और एक त्रुटि संकेतक के रूप में किया जाता है, और एक अशक्त सूचक (एक अशक्त सूचक के माध्यम से पढ़ना या लिखना) को संदर्भित करना एक बहुत ही सामान्य कार्यक्रम त्रुटि है। सी मानक यह नहीं कहता है कि शून्य सूचक [[स्मृति पता]] 0 के सूचक के समान है, हालांकि व्यवहार में ऐसा हो सकता है। अधिकांश ऑपरेटिंग | सी और सी-जैसी भाषाओं में, अशक्त संकेतकों का उपयोग बिना किसी वस्तु के संकेतक और एक त्रुटि संकेतक के रूप में किया जाता है, और एक अशक्त सूचक (एक अशक्त सूचक के माध्यम से पढ़ना या लिखना) को संदर्भित करना एक बहुत ही सामान्य कार्यक्रम त्रुटि है। सी मानक यह नहीं कहता है कि शून्य सूचक [[स्मृति पता]] 0 के सूचक के समान है, हालांकि व्यवहार में ऐसा हो सकता है। अधिकांश ऑपरेटिंग प्रणाली नल पॉइंटर के पते को इस तरह से मैप करते हैं कि इसे एक्सेस करने से सेगमेंटेशन त्रुटि हो जाती है। सी मानक द्वारा इस व्यवहार की गारंटी नहीं है। एक अशक्त सूचक को संदर्भित करना C में अपरिभाषित व्यवहार है, और एक अनुरूप कार्यान्वयन को यह मानने की अनुमति है कि कोई भी सूचक जो अशक्त है, अशक्त नहीं है। | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
Line 100: | Line 100: | ||
printf("%d", *ptr); | printf("%d", *ptr); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
यह नमूना कोड एक शून्य सूचक बनाता है, और फिर इसके मान तक पहुँचने का प्रयास करता है (मान पढ़ें)। ऐसा करने से कई ऑपरेटिंग | यह नमूना कोड एक शून्य सूचक बनाता है, और फिर इसके मान तक पहुँचने का प्रयास करता है (मान पढ़ें)। ऐसा करने से कई ऑपरेटिंग प्रणाली पर रनटाइम में सेगमेंटेशन त्रुटि हो जाती है। | ||
एक अशक्त सूचक को हटाना और फिर उसे निर्दिष्ट करना (एक गैर-मौजूद लक्ष्य के लिए एक मान लिखना) भी | एक अशक्त सूचक को हटाना और फिर उसे निर्दिष्ट करना (एक गैर-मौजूद लक्ष्य के लिए एक मान लिखना) भी सामान्यतः एक विभाजन दोष का कारण बनता है: | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
int *ptr = NULL; | int *ptr = NULL; | ||
*ptr = 1; | *ptr = 1; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
निम्नलिखित कोड में एक नल पॉइंटर डिरेफरेंस शामिल है, | निम्नलिखित कोड में एक नल पॉइंटर डिरेफरेंस शामिल है, किन्तु जब संकलित किया जाता है तो प्रायः सेगमेंटेशन त्रुटि नहीं होती है, क्योंकि मूल्य अप्रयुक्त होता है और इस प्रकार डीरेफरेंस को प्रायः [[मृत कोड उन्मूलन]] द्वारा अनुकूलित किया जाएगा: | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
int *ptr = NULL; | int *ptr = NULL; | ||
Line 134: | Line 134: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
जो [[ स्टैक ओवरफ़्लो ]] का कारण बनता है जिसके परिणामस्वरूप सेगमेंटेशन | जो [[ स्टैक ओवरफ़्लो ]] का कारण बनता है जिसके परिणामस्वरूप सेगमेंटेशन त्रुटि होती है।<ref>[https://stackoverflow.com/questions/2685413/what-is-the-difference-between-a-segmentation-fault-and-a-stack-overflow/2685434#2685434 What is the difference between a segmentation fault and a stack overflow?] at [[Stack Overflow]]</ref> भाषा, संकलक द्वारा किए गए अनुकूलन और कोड की सटीक संरचना के आधार पर अनंत पुनरावर्तन आवश्यक रूप से स्टैक ओवरफ़्लो का परिणाम नहीं हो सकता है। इस मामले में, अगम्य कोड (रिटर्न स्टेटमेंट) का व्यवहार अपरिभाषित है, इसलिए कंपाइलर इसे समाप्त कर सकता है और [[टेल कॉल]] ऑप्टिमाइज़ेशन का उपयोग कर सकता है जिसके परिणामस्वरूप कोई स्टैक उपयोग नहीं हो सकता है। अन्य अनुकूलन में पुनरावर्तन को पुनरावृत्ति में अनुवाद करना शामिल हो सकता है, जो उदाहरण फ़ंक्शन की संरचना को देखते हुए प्रोग्राम को हमेशा के लिए चलाने में परिणाम देगा, जबकि संभवतः इसके स्टैक को ओवरफ्लो नहीं करेगा। | ||
== यह भी देखें == | == यह भी देखें == |
Revision as of 11:28, 28 April 2023
कम्प्यूटिंग में, विभाजन दोष या एक्सेस उल्लंघन दोष (कंप्यूटिंग), या विफलता की स्थिति है, जो मेमोरी सुरक्षा के साथ हार्डवेयर द्वारा उठाया जाता है, ऑपरेटिंग प्रणाली (OS) को सूचित करता है, सॉफ्टवेयर ने प्रतिबंधित क्षेत्र तक पहुंचने का प्रयास किया है। मेमोरी ( मेमोरी एक्सेस उल्लंघन) मानक x86 कंप्यूटरों पर, यह सामान्य सुरक्षा दोष का रूप है। ऑपरेटिंग प्रणाली कर्नेल, प्रतिक्रिया में, सामान्यतः कुछ सुधारात्मक कार्रवाई करता है, सामान्यतः प्रक्रिया को संकेत (कंप्यूटिंग) भेजकर त्रुटि को आपत्तिजनक प्रक्रिया (कंप्यूटिंग) पर भेज देता है। प्रक्रियाएं कुछ स्थितियों में कस्टम सिग्नल हैंडलर स्थापित कर सकती हैं, जिससे उन्हें स्वयं ठीक होने की अनुमति मिलती है,[1] अन्यथा ओएस डिफ़ॉल्ट सिग्नल हैंडलर का उपयोग किया जाता है, सामान्यतः प्रक्रिया की असामान्य समाप्ति (प्रोग्राम क्रैश (कंप्यूटिंग)), और कभी-कभी कोर निपात होता है।
सेगमेंटेशन दोष सी (प्रोग्रामिंग भाषा) जैसी भाषाओं में लिखे गए प्रोग्रामों में त्रुटि का एक सामान्य वर्ग है जो निम्न-स्तरीय मेमोरी एक्सेस प्रदान करता है और कुछ से लेकर कोई सुरक्षा जांच नहीं करता है। वे मुख्य रूप से आभासी मेमोरी एड्रेसिंग के लिए पॉइंटर (कंप्यूटर प्रोग्रामिंग) के उपयोग में त्रुटियों के कारण उत्पन्न होते हैं, विशेष रूप से अवैध पहुंच के कारण। एक अन्य प्रकार की मेमोरी एक्सेस त्रुटि एक बस त्रुटि है, जिसके विभिन्न कारण भी हैं, किन्तु आज यह बहुत दुर्लभ है; ये मुख्य रूप से गलत भौतिक मेमोरी एड्रेसिंग के कारण होते हैं, या गलत तरीके से मेमोरी एक्सेस के कारण होते हैं - ये ऐसे मेमोरी रेफरेंस होते हैं जिन्हें हार्डवेयर एड्रेस नहीं कर सकता है, बजाय उन रेफरेंस के जिन्हें एड्रेस करने की अनुमति नहीं है।
कई प्रोग्रामिंग लैंग्वेज सेगमेंटेशन दोषों से बचने और मेमोरी सुरक्षा में सुधार के लिए डिज़ाइन किए गए तंत्रों को नियोजित कर सकती हैं। उदाहरण के लिए, जंग (प्रोग्रामिंग भाषा) एक स्वामित्व-आधारित को नियोजित करता है[2] स्मृति सुरक्षा सुनिश्चित करने के लिए मॉडल।[3] अन्य भाषाएँ, जैसे कि लिस्प (प्रोग्रामिंग भाषा) और जावा (प्रोग्रामिंग भाषा), कचरा संग्रह (कंप्यूटर विज्ञान) को नियोजित करती हैं,[4] जो स्मृति त्रुटियों के कुछ वर्गों से बचा जाता है जिससे विभाजन दोष हो सकते हैं।[5]
सिंहावलोकन
सेगमेंटेशन फॉल्ट तब होता है जब कोई प्रोग्राम स्मृति लोकेशन तक पहुंचने का प्रयास करता है जिसे एक्सेस करने की अनुमति नहीं है, या किसी मेमोरी लोकेशन को इस तरह एक्सेस करने का प्रयास करता है जिसकी अनुमति नहीं है (उदाहरण के लिए, केवल पढ़ने के लिये मेमोरी में लिखने का प्रयास | रीड-ओनली लोकेशन, या ऑपरेटिंग प्रणाली के हिस्से को ओवरराइट करने के लिए)।
शब्द विभाजन के कंप्यूटिंग में विभिन्न उपयोग हैं; सेगमेंटेशन फॉल्ट के संदर्भ में, 1950 के दशक से इस्तेमाल किया जाने वाला शब्द,[citation needed] यह किसी प्रोग्राम के एड्रेस स्पेस को संदर्भित करता है।[6] स्मृति सुरक्षा के साथ, केवल प्रोग्राम का अपना पता स्थान ही पढ़ने योग्य होता है, और इसमें से केवल कॉल स्टैक और प्रोग्राम के डेटा सेगमेंट का रीड/राइट भाग लिखने योग्य होता है, जबकि रीड-ओनली डेटा और कोड खंड लिखने योग्य नहीं होते हैं। इस प्रकार प्रोग्राम के एड्रेस स्पेस के बाहर पढ़ने का प्रयास, या एड्रेस स्पेस के रीड-ओनली सेगमेंट में लिखने से सेगमेंटेशन फॉल्ट होता है, इसलिए नाम।
वर्चुअल मेमोरी प्रदान करने के लिए हार्डवेयर स्मृति विभाजन का उपयोग करने वाले प्रणाली पर, सेगमेंटेशन त्रुटि तब होती है जब हार्डवेयर गैर-मौजूद सेगमेंट को संदर्भित करने का प्रयास करता है, डेटा खंड की सीमाओं के बाहर किसी स्थान को संदर्भित करता है, या किसी स्थान को संदर्भित करता है। उस सेगमेंट के लिए दी गई अनुमतियों द्वारा अनुमत फैशन नहीं। केवल पेजिंग का उपयोग करने वाले प्रणाली पर, एक अमान्य पृष्ठ दोष सामान्यतः एक विभाजन दोष की ओर जाता है, और विभाजन दोष और पृष्ठ दोष दोनों ही वर्चुअल मेमोरी मैनेजमेंट प्रणाली द्वारा उठाए गए दोष हैं। सेगमेंटेशन दोष पृष्ठ दोषों से स्वतंत्र रूप से भी हो सकते हैं: वैध पृष्ठ तक अवैध पहुंच एक सेगमेंटेशन त्रुटि है, किन्तु अमान्य पृष्ठ त्रुटि नहीं है, और सेगमेंटेशन दोष पृष्ठ के मध्य में हो सकते हैं (इसलिए कोई पृष्ठ त्रुटि नहीं है), उदाहरण के लिए बफ़र अधिकता जो एक पृष्ठ के भीतर रहता है किन्तु अवैध रूप से स्मृति को अधिलेखित कर देता है।
हार्डवेयर स्तर पर, स्मृति प्रबंधन इकाई (एमएमयू) द्वारा अवैध पहुंच (यदि संदर्भित मेमोरी मौजूद है) द्वारा इसकी स्मृति सुरक्षा सुविधा के भाग के रूप में, या एक अमान्य पृष्ठ दोष (यदि संदर्भित स्मृति मौजूद नहीं है) द्वारा शुरू में त्रुटि उठाई जाती है ). यदि समस्या एक अमान्य तार्किक पता नहीं है बल्कि एक अमान्य भौतिक पता है, तो इसके बजाय एक बस त्रुटि उठाई जाती है, हालांकि ये हमेशा अलग नहीं होते हैं।
ऑपरेटिंग प्रणाली के स्तर पर, यह त्रुटि पकड़ी जाती है और उस सिग्नल के लिए प्रक्रिया के हैंडलर को सक्रिय करते हुए, आपत्तिजनक प्रक्रिया को एक संकेत दिया जाता है। अलग-अलग ऑपरेटिंग प्रणाली में अलग-अलग सिग्नल नाम होते हैं जो इंगित करते हैं कि सेगमेंटेशन त्रुटि हुई है। यूनिक्स जैसे ऑपरेटिंग प्रणाली पर, SIGSEGV नामक एक सिग्नल (विभाजन उल्लंघन से संक्षिप्त) को आपत्तिजनक प्रक्रिया के लिए भेजा जाता है। Microsoft Windows पर, आपत्तिजनक प्रक्रिया को एक STATUS_ACCESS_VIOLATION अपवाद प्रबंधन प्राप्त होता है।
कारण
जिन परिस्थितियों में सेगमेंटेशन का उल्लंघन होता है और वे खुद को कैसे प्रकट करते हैं, वे हार्डवेयर और ऑपरेटिंग प्रणाली के लिए विशिष्ट हैं: अलग-अलग हार्डवेयर दी गई शर्तों के लिए अलग-अलग दोष पैदा करते हैं, और अलग-अलग ऑपरेटिंग प्रणाली इन्हें अलग-अलग सिग्नल में परिवर्तित करते हैं जो प्रक्रियाओं पर पारित होते हैं। निकटस्थ कारण एक मेमोरी एक्सेस उल्लंघन है, जबकि अंतर्निहित कारण सामान्यतः किसी प्रकार का सॉफ्टवेयर बग है। मूल कारण विश्लेषण का निर्धारण - बग को डिबग करना - कुछ मामलों में सरल हो सकता है, जहां प्रोग्राम लगातार सेगमेंटेशन त्रुटि का कारण बनता है (उदाहरण के लिए, शून्य सूचक को संदर्भित करना), जबकि अन्य मामलों में बग को पुन: पेश करना और स्मृति पर निर्भर करना मुश्किल हो सकता है प्रत्येक रन पर आवंटन (उदाहरण के लिए, झूलने वाले सूचक को संदर्भित करना)।
विभाजन दोष के कुछ विशिष्ट कारण निम्नलिखित हैं:
- एक गैर-मौजूद स्मृति पते तक पहुँचने का प्रयास (प्रक्रिया के पता स्थान के बाहर)
- स्मृति तक पहुँचने का प्रयास कार्यक्रम के पास अधिकार नहीं है (जैसे कि प्रक्रिया के संदर्भ में कर्नेल संरचनाएँ)
- रीड-ओनली मेमोरी (जैसे कोड सेगमेंट) लिखने का प्रयास
ये बदले में प्रायः प्रोग्रामिंग त्रुटियों के कारण होते हैं, जिसके परिणामस्वरूप अमान्य मेमोरी एक्सेस होती है:
- एक अशक्त सूचक को संदर्भित करना, जो सामान्यतः एक ऐसे पते की ओर इशारा करता है जो प्रक्रिया के पता स्थान का हिस्सा नहीं है
- एक गैर-प्रारंभिक सूचक (जंगली सूचक, जो एक यादृच्छिक स्मृति पते को इंगित करता है) को संदर्भित या असाइन करना
- फ्रीड पॉइंटर को डिफ्रेंसिंग या असाइन करना (झूलने वाला पॉइंटर, जो उस मेमोरी को इंगित करता है जिसे मुक्त/डीललोकेटेड/डिलीट किया गया है)
- एक बफर अतिप्रवाह
- स्टैक ओवरफ़्लो
- ऐसे प्रोग्राम को निष्पादित करने का प्रयास करना जो सही ढंग से संकलित नहीं होता है। (कुछ संकलक[which?] संकलन-समय त्रुटियों की उपस्थिति के बावजूद निष्पादन योग्य फ़ाइल आउटपुट करेगा।)
सी कोड में, सेगमेंटेशन दोष प्रायः पॉइंटर उपयोग में त्रुटियों के कारण होते हैं, खासकर सी गतिशील स्मृति आवंटन में। अशक्त सूचक को संदर्भित करना, जिसके परिणामस्वरूप अपरिभाषित व्यवहार होता है, सामान्यतः एक विभाजन दोष का कारण होगा। ऐसा इसलिए है क्योंकि एक शून्य सूचक वैध स्मृति पता नहीं हो सकता है। दूसरी ओर, वाइल्ड पॉइंटर्स और डैंगलिंग पॉइंटर्स उस मेमोरी की ओर इशारा करते हैं जो मौजूद हो भी सकती है और नहीं भी, और पढ़ने योग्य या लिखने योग्य हो भी सकती है और नहीं भी, और इस प्रकार क्षणिक बग का परिणाम हो सकता है। उदाहरण के लिए:
char *p1 = NULL; // Null pointer
char *p2; // Wild pointer: not initialized at all.
char *p3 = malloc(10 * sizeof(char)); // Initialized pointer to allocated memory
// (assuming malloc did not fail)
free(p3); // p3 is now a dangling pointer, as memory has been freed
इनमें से किसी भी वेरिएबल को डिफ्रेंस करने से सेगमेंटेशन फॉल्ट हो सकता है: नल पॉइंटर को डीरेफर करने से सामान्यतः एक सेगफॉल्ट होता है, जबकि वाइल्ड पॉइंटर से पढ़ने के बजाय रैंडम डेटा हो सकता है, किन्तु कोई सेगफॉल्ट नहीं होता है, और डैंगलिंग पॉइंटर से पढ़ने के परिणामस्वरूप वैध डेटा हो सकता है। जबकि, और फिर यादृच्छिक डेटा, क्योंकि यह ओवरराइट किया गया है।
हैंडलिंग
सेगमेंटेशन त्रुटि या बस त्रुटि के लिए डिफ़ॉल्ट क्रिया उस प्रक्रिया की असामान्य समाप्ति है जिसने इसे ट्रिगर किया। डिबगिंग में सहायता के लिए एक कोर फ़ाइल उत्पन्न की जा सकती है, और अन्य प्लेटफ़ॉर्म-निर्भर क्रियाएं भी की जा सकती हैं। उदाहरण के लिए, ग्रसिक्युरिटी पैच का उपयोग करने वाले लिनक्स प्रणाली बफर ओवरफ्लो का उपयोग करके संभावित घुसपैठ के प्रयासों की निगरानी के लिए SIGSEGV संकेतों को लॉग कर सकते हैं।
कुछ प्रणालियों पर, जैसे कि लिनक्स और विंडोज, यह संभव है कि कार्यक्रम स्वयं एक विभाजन दोष को संभाले।[7] आर्किटेक्चर और ऑपरेटिंग प्रणाली के आधार पर, रनिंग प्रोग्राम न केवल ईवेंट को हैंडल कर सकता है, बल्कि इसकी स्थिति के बारे में कुछ जानकारी निकाल सकता है जैसे स्टैक ट्रेस प्राप्त करना, प्रोसेसर रजिस्टर वैल्यू, स्रोत कोड की लाइन जब इसे ट्रिगर किया गया था, मेमोरी एड्रेस जो था अमान्य रूप से एक्सेस किया गया[8] और क्या कार्रवाई पढ़ी गई या लिखी गई थी।[9] हालांकि एक सेगमेंटेशन त्रुटि का सामान्यतः मतलब है कि प्रोग्राम में एक बग है जिसे ठीक करने की आवश्यकता है, जानबूझकर ऐसी विफलता का कारण परीक्षण, डिबगिंग और प्लेटफॉर्म का अनुकरण करना भी संभव है जहां मेमोरी तक सीधी पहुंच की आवश्यकता है। बाद वाले मामले में, प्रणाली को त्रुटि होने के बाद भी प्रोग्राम को चलाने की अनुमति देने में सक्षम होना चाहिए। इस मामले में, जब प्रणाली अनुमति देता है, तो घटना को संभालना और निष्पादन जारी रखने के लिए असफल निर्देश पर कूदने के लिए प्रोसेसर प्रोग्राम काउंटर को बढ़ाना संभव है।[10]
उदाहरण
रीड ओनली मेमोरी में लिखना
रीड-ओनली मेमोरी में लिखने से सेगमेंटेशन फॉल्ट होता है। कोड त्रुटियों के स्तर पर, यह तब होता है जब प्रोग्राम अपने स्वयं के कोड सेगमेंट या डेटा सेगमेंट के रीड-ओनली हिस्से को लिखता है, क्योंकि ये OS द्वारा रीड-ओनली मेमोरी में लोड किए जाते हैं।
यहां एएनएसआई सी कोड का एक उदाहरण दिया गया है जो सामान्यतः स्मृति सुरक्षा वाले प्लेटफॉर्म पर सेगमेंटेशन त्रुटि का कारण बनता है। यह एक स्ट्रिंग शाब्दिक को संशोधित करने का प्रयास करता है, जो एएनएसआई सी मानक के अनुसार अपरिभाषित व्यवहार है। अधिकांश संकलक इसे संकलित समय पर नहीं पकड़ेंगे, और इसके बजाय इसे निष्पादन योग्य कोड में संकलित करेंगे जो क्रैश हो जाएगा:
int main(void)
{
char *s = "hello world";
*s = 'H';
}
जब इस कोड वाले प्रोग्राम को संकलित किया जाता है, तो स्ट्रिंग हैलो वर्ल्ड को प्रोग्राम एक्जीक्यूटेबल फ़ाइल के रोडाटा सेक्शन में रखा जाता है: डेटा सेगमेंट का रीड-ओनली सेक्शन। जब लोड किया जाता है, तो ऑपरेटिंग प्रणाली इसे अन्य स्ट्रिंग्स और निरंतर (प्रोग्रामिंग) डेटा के साथ मेमोरी के रीड-ओनली सेगमेंट में रखता है। जब निष्पादित किया जाता है, तो एक चर, s, स्ट्रिंग के स्थान को इंगित करने के लिए सेट किया जाता है, और चर के माध्यम से स्मृति में H वर्ण लिखने का प्रयास किया जाता है, जिससे विभाजन दोष उत्पन्न होता है। ऐसे प्रोग्राम को एक कंपाइलर के साथ संकलित करना जो संकलन समय पर केवल-पढ़ने के लिए स्थानों के असाइनमेंट की जांच नहीं करता है, और इसे यूनिक्स-जैसे ऑपरेटिंग प्रणाली पर चलाने से निम्न रनटाइम त्रुटि उत्पन्न होती है:
$ gcc segfault.c -g -o segfault
$ ./segfault
Segmentation fault
जीडीबी से कोर फ़ाइल का पश्व-अनुरेखन:
Program received signal SIGSEGV, Segmentation fault.
0x1c0005c2 in main () at segfault.c:6
6 *s = 'H';
इस कोड को वर्ण सूचक के बजाय सरणी का उपयोग करके ठीक किया जा सकता है, क्योंकि यह ढेर पर स्मृति आवंटित करता है और इसे स्ट्रिंग अक्षर के मान में प्रारंभ करता है:
char s[] = "hello world";
s[0] = 'H'; // equivalently, *s = 'H';
भले ही स्ट्रिंग अक्षर को संशोधित नहीं किया जाना चाहिए (यह सी मानक में अपरिभाषित व्यवहार है), सी में वे हैं static char []
प्रकार,[11][12][13] इसलिए मूल कोड में कोई निहित रूपांतरण नहीं है (जो इंगित करता है a char *
उस सरणी में), जबकि सी ++ में वे हैं static const char []
प्रकार, और इस प्रकार एक निहित रूपांतरण होता है, इसलिए संकलक सामान्यतः इस विशेष त्रुटि को पकड़ लेंगे।
अशक्त सूचक dereference
सी और सी-जैसी भाषाओं में, अशक्त संकेतकों का उपयोग बिना किसी वस्तु के संकेतक और एक त्रुटि संकेतक के रूप में किया जाता है, और एक अशक्त सूचक (एक अशक्त सूचक के माध्यम से पढ़ना या लिखना) को संदर्भित करना एक बहुत ही सामान्य कार्यक्रम त्रुटि है। सी मानक यह नहीं कहता है कि शून्य सूचक स्मृति पता 0 के सूचक के समान है, हालांकि व्यवहार में ऐसा हो सकता है। अधिकांश ऑपरेटिंग प्रणाली नल पॉइंटर के पते को इस तरह से मैप करते हैं कि इसे एक्सेस करने से सेगमेंटेशन त्रुटि हो जाती है। सी मानक द्वारा इस व्यवहार की गारंटी नहीं है। एक अशक्त सूचक को संदर्भित करना C में अपरिभाषित व्यवहार है, और एक अनुरूप कार्यान्वयन को यह मानने की अनुमति है कि कोई भी सूचक जो अशक्त है, अशक्त नहीं है।
int *ptr = NULL;
printf("%d", *ptr);
यह नमूना कोड एक शून्य सूचक बनाता है, और फिर इसके मान तक पहुँचने का प्रयास करता है (मान पढ़ें)। ऐसा करने से कई ऑपरेटिंग प्रणाली पर रनटाइम में सेगमेंटेशन त्रुटि हो जाती है।
एक अशक्त सूचक को हटाना और फिर उसे निर्दिष्ट करना (एक गैर-मौजूद लक्ष्य के लिए एक मान लिखना) भी सामान्यतः एक विभाजन दोष का कारण बनता है:
int *ptr = NULL;
*ptr = 1;
निम्नलिखित कोड में एक नल पॉइंटर डिरेफरेंस शामिल है, किन्तु जब संकलित किया जाता है तो प्रायः सेगमेंटेशन त्रुटि नहीं होती है, क्योंकि मूल्य अप्रयुक्त होता है और इस प्रकार डीरेफरेंस को प्रायः मृत कोड उन्मूलन द्वारा अनुकूलित किया जाएगा:
int *ptr = NULL;
*ptr;
बफर अतिप्रवाह
निम्न कोड वर्ण सरणी तक पहुँचता है s
इसकी ऊपरी सीमा से परे। संकलक और प्रोसेसर के आधार पर, इसका परिणाम विभाजन दोष हो सकता है।
char s[] = "hello world";
char c = s[20];
ढेर अतिप्रवाह
आधार मामले के बिना एक और उदाहरण प्रत्यावर्तन है:
int main(void)
{
return main();
}
जो स्टैक ओवरफ़्लो का कारण बनता है जिसके परिणामस्वरूप सेगमेंटेशन त्रुटि होती है।[14] भाषा, संकलक द्वारा किए गए अनुकूलन और कोड की सटीक संरचना के आधार पर अनंत पुनरावर्तन आवश्यक रूप से स्टैक ओवरफ़्लो का परिणाम नहीं हो सकता है। इस मामले में, अगम्य कोड (रिटर्न स्टेटमेंट) का व्यवहार अपरिभाषित है, इसलिए कंपाइलर इसे समाप्त कर सकता है और टेल कॉल ऑप्टिमाइज़ेशन का उपयोग कर सकता है जिसके परिणामस्वरूप कोई स्टैक उपयोग नहीं हो सकता है। अन्य अनुकूलन में पुनरावर्तन को पुनरावृत्ति में अनुवाद करना शामिल हो सकता है, जो उदाहरण फ़ंक्शन की संरचना को देखते हुए प्रोग्राम को हमेशा के लिए चलाने में परिणाम देगा, जबकि संभवतः इसके स्टैक को ओवरफ्लो नहीं करेगा।
यह भी देखें
- सामान्य संरक्षण त्रुटि
- भंडारण उल्लंघन
- गुरु ध्यान
संदर्भ
- ↑ Expert C programming: deep C secrets By Peter Van der Linden, page 188
- ↑ "The Rust Programming Language - Ownership".
- ↑ "Fearless Concurrency with Rust - The Rust Programming Language Blog".
- ↑ McCarthy, John (April 1960). "सांकेतिक भावों के पुनरावर्ती कार्य और मशीन द्वारा उनकी गणना, भाग I". Communications of the ACM. 4 (3): 184–195. doi:10.1145/367177.367199. S2CID 1489409. Retrieved 2018-09-22.
- ↑ Dhurjati, Dinakar; Kowshik, Sumant; Adve, Vikram; Lattner, Chris (1 January 2003). "मेमोरी सुरक्षा रनटाइम चेक या कचरा संग्रह के बिना" (PDF). Proceedings of the 2003 ACM SIGPLAN Conference on Language, Compiler, and Tool for Embedded Systems (in English). ACM. 38 (7): 69–80. doi:10.1145/780732.780743. ISBN 1581136471. S2CID 1459540. Retrieved 2018-09-22.
- ↑ "डिबगिंग विभाजन दोष और सूचक समस्याएं - Cprogramming.com". www.cprogramming.com. Retrieved 2021-02-03.
- ↑ "Cleanly recovering from Segfaults under Windows and Linux (32-bit, x86)". Retrieved 2020-08-23.
- ↑ "Implementation of the SIGSEGV/SIGABRT handler which prints the debug stack trace". GitHub. Retrieved 2020-08-23.
- ↑ "How to identify read or write operations of page fault when using sigaction handler on SIGSEGV?(LINUX)". Retrieved 2020-08-23.
- ↑ "LINUX – WRITING FAULT HANDLERS". Retrieved 2020-08-23.
- ↑ "6.1.4 String literals". ISO/IEC 9899:1990 - Programming languages -- C.
- ↑ "6.4.5 String literals". ISO/IEC 9899:1999 - Programming languages -- C.
- ↑ "6.4.5 String literals". ISO/IEC 9899:2011 - Programming languages -- C.
- ↑ What is the difference between a segmentation fault and a stack overflow? at Stack Overflow