अपरिभाषित व्यवहार

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

C (प्रोग्रामिंग लैंग्वेज) में, अपरिभाषित व्यवहार को मज़ाक के तौर पर नेसल डेमोंस कहा जा सकता है, एक COMP.* hierarchy|comp.std.c पोस्ट के बाद, जो अपरिभाषित व्यवहार की व्याख्या करता है, क्योंकि यह कंपाइलर को कुछ भी करने की अनुमति देता है, यहां तक ​​कि राक्षसों को बनाने के लिए भी अपनी नाक से बाहर उड़ो।

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

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

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

वर्तमान कंपाइलर विकास आमतौर पर माइक्रो-ऑप्टिमाइज़ेशन के आसपास डिज़ाइन किए गए बेंचमार्क के साथ कंपाइलर प्रदर्शन का मूल्यांकन और तुलना करता है, यहां तक ​​कि उन प्लेटफॉर्म पर भी जो सामान्य प्रयोजन के डेस्कटॉप और लैपटॉप बाजार (जैसे amd64) पर उपयोग किए जाते हैं। इसलिए, अपरिभाषित व्यवहार संकलक प्रदर्शन में सुधार के लिए पर्याप्त जगह प्रदान करता है, क्योंकि एक विशिष्ट स्रोत कोड स्टेटमेंट के लिए स्रोत कोड को रनटाइम पर कुछ भी मैप करने की अनुमति है।

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

कुछ परिस्थितियों में अपरिभाषित व्यवहार पर विशिष्ट प्रतिबंध हो सकते हैं। उदाहरण के लिए, एक केंद्रीय प्रसंस्करण इकाई के निर्देश सेट विनिर्देश निर्देश के कुछ रूपों के व्यवहार को अपरिभाषित छोड़ सकते हैं, लेकिन यदि सीपीयू मेमोरी सुरक्षा का समर्थन करता है, तो विनिर्देश में संभवतः एक कंबल नियम शामिल होगा, जिसमें कहा गया है कि कोई उपयोगकर्ता-पहुंच योग्य निर्देश नहीं हो सकता है। ऑपरेटिंग सिस्टम की सुरक्षा में छेद; इसलिए एक वास्तविक सीपीयू को ऐसे निर्देश के जवाब में उपयोगकर्ता रजिस्टरों को दूषित करने की अनुमति दी जाएगी, लेकिन इसकी अनुमति नहीं दी जाएगी, उदाहरण के लिए, पर्यवेक्षक मोड में स्विच करना।

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

अपरिभाषित व्यवहार के परिणामस्वरूप प्रोग्राम क्रैश हो सकता है या विफलताओं में भी हो सकता है जो कि पता लगाने में कठिन हैं और प्रोग्राम को सामान्य रूप से काम करने जैसा दिखता है, जैसे कि डेटा की साइलेंट हानि और गलत परिणामों का उत्पादन।

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

सी भाषा के लिए एक उदाहरण:

का मान है  ऋणात्मक नहीं हो सकता है और, यह देखते हुए कि हस्ताक्षरित पूर्णांक अतिप्रवाह सी में अपरिभाषित व्यवहार है, संकलक यह मान सकता है   हमेशा झूठा रहेगा। इस प्रकार   बयान, समारोह के लिए कॉल सहित , में परीक्षण अभिव्यक्ति के बाद से संकलक द्वारा अनदेखा किया जा सकता है   इसका कोई साइड इफेक्ट (कंप्यूटर साइंस) नहीं है और इसकी स्थिति कभी भी संतुष्ट नहीं होगी। कोड इसलिए शब्दार्थ के बराबर है:

यदि संकलक को यह मानने के लिए मजबूर किया गया था कि हस्ताक्षरित पूर्णांक अतिप्रवाह में रैपराउंड व्यवहार है, तो उपरोक्त परिवर्तन कानूनी नहीं होता।

जब कोड अधिक जटिल होता है और इनलाइनिंग जैसे अन्य अनुकूलन होते हैं, तो इस तरह के अनुकूलन मनुष्यों द्वारा खोजना मुश्किल हो जाता है। उदाहरण के लिए, कोई अन्य फ़ंक्शन उपरोक्त फ़ंक्शन को कॉल कर सकता है:

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

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

जोखिम
सी और सी ++ मानकों में अपरिभाषित व्यवहार के कई रूप हैं, जो संकलक कार्यान्वयन में वृद्धि की स्वतंत्रता प्रदान करते हैं और वर्तमान में अपरिभाषित रन-टाइम व्यवहार की कीमत पर संकलन-समय की जांच करते हैं। विशेष रूप से, सी के लिए मानकीकरण मानक के लिए अंतर्राष्ट्रीय संगठन में अपरिभाषित व्यवहार के सामान्य स्रोतों को सूचीबद्ध करने वाला एक परिशिष्ट है। इसके अलावा, अपरिभाषित व्यवहार पर निर्भर कोड का निदान करने के लिए संकलक की आवश्यकता नहीं होती है। इसलिए, प्रोग्रामर, यहां तक ​​​​कि अनुभवी लोगों के लिए, अपरिभाषित व्यवहार पर या तो गलती से भरोसा करना आम बात है, या केवल इसलिए कि वे भाषा के नियमों से अच्छी तरह वाकिफ नहीं हैं जो सैकड़ों पृष्ठों को फैला सकते हैं। इसका परिणाम उन बगों में हो सकता है जो एक अलग कंपाइलर, या अलग-अलग सेटिंग्स का उपयोग करते समय सामने आते हैं। सक्रिय अपरिभाषित व्यवहार जांच के साथ परीक्षण या फज़िंग सक्षम, उदाहरण के लिए, क्लैंग सैनिटाइज़र, अपरिभाषित व्यवहार को पकड़ने में मदद कर सकता है जो संकलक या स्थिर विश्लेषक द्वारा निदान नहीं किया गया है। अपरिभाषित व्यवहार से सॉफ़्टवेयर में कंप्यूटर सुरक्षा भेद्यता हो सकती है। उदाहरण के लिए, प्रमुख वेब ब्राउज़रों में बफर ओवरफ्लो और अन्य सुरक्षा कमजोरियां अपरिभाषित व्यवहार के कारण होती हैं। जब GNU C कंपाइलर के डेवलपर्स ने 2008 में अपने कंपाइलर को इस तरह बदल दिया कि यह कुछ ओवरफ्लो चेक को छोड़ देता है जो अपरिभाषित व्यवहार पर निर्भर करता है, CERT समन्वय केंद्र ने कंपाइलर के नए संस्करणों के खिलाफ चेतावनी जारी की। लिनक्स साप्ताहिक समाचार  ने बताया कि समान व्यवहार PathScale, Visual C++|Microsoft Visual C++ 2005 और कई अन्य कंपाइलरों में देखा गया था; चेतावनी को बाद में विभिन्न संकलकों के बारे में चेतावनी देने के लिए संशोधित किया गया था।

सी और सी ++
में उदाहरण

सी में अपरिभाषित व्यवहार के प्रमुख रूपों को मोटे तौर पर वर्गीकृत किया जा सकता है: स्थानिक स्मृति सुरक्षा उल्लंघन, अस्थायी स्मृति सुरक्षा उल्लंघन, पूर्णांक अतिप्रवाह, सख्त अलियासिंग उल्लंघन, संरेखण उल्लंघन, अनुक्रमित संशोधन, डेटा दौड़, और लूप जो न तो I/O निष्पादित करते हैं और न ही समाप्त होते हैं।

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

एक स्ट्रिंग शाब्दिक को संशोधित करने का प्रयास अपरिभाषित व्यवहार का कारण बनता है: ISO/IEC 14882|ISO/IEC 14882:2003(E): प्रोग्रामिंग लैंग्वेज - C++ §2.13.4 शाब्दिक स्ट्रिंग  [lex.string] पैरा। 2 अपरिभाषित व्यवहार में शून्य परिणामों से पूर्णांक विभाजन: आधुनिक कंपाइलर चेतावनियों का उत्सर्जन कर सकते हैं जब वे एक ही वस्तु में कई अप्रतिबंधित संशोधनों का सामना करते हैं। निम्न उदाहरण सी और सी ++ दोनों में अपरिभाषित व्यवहार का कारण बनता है। दो अनुक्रम बिंदुओं के बीच किसी वस्तु को संशोधित करते समय, संग्रहित किए जाने वाले मूल्य को निर्धारित करने के अलावा किसी अन्य उद्देश्य के लिए वस्तु के मूल्य को पढ़ना भी अपरिभाषित व्यवहार है। ). ISO/IEC 9899|ISO/IEC 9899:1999(E): प्रोग्रामिंग लैंग्वेज - C §6.5 एक्सप्रेशंस पैरा। 2 सी/सी++ में तार्किक पारी  एक मान को कई बिट्स द्वारा बदलता है जो या तो ऋणात्मक संख्या है या इस मूल्य में बिट्स की कुल संख्या से अधिक या बराबर है, जिसके परिणामस्वरूप अपरिभाषित व्यवहार होता है। सबसे सुरक्षित तरीका (संकलक विक्रेता की परवाह किए बिना) हमेशा बिट्स की संख्या को शिफ्ट करने के लिए रखना है (संचालन का सही संचालन)   और   बिटवाइज़ ऑपरेशन) सीमा के भीतर: < > (जहां   बायां ऑपरेंड है)।

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

ध्यान दें कि संदर्भ का उपयोग करना आवश्यक नहीं है; इस तरह के संदर्भ के निर्माण से ही अपरिभाषित व्यवहार का आह्वान किया जाता है।

यह भी देखें

 * संकलक
 * रोकें और आग पकड़ें (कंप्यूटिंग)
 * अनिर्दिष्ट व्यवहार

अग्रिम पठन

 * Peter van der Linden, Expert C Programming. ISBN 0-13-177429-8
 * UB Canaries (April 2015), John Regehr (University of Utah, USA)
 * Undefined Behavior in 2017 (July 2017) Pascal Cuoq (TrustInSoft, France) and John Regehr (University of Utah, USA)

बाहरी संबंध

 * Corrected version of the C99 standard. Look at section 6.10.6 for #pragma