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

From Vigyanwiki

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

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


सिंहावलोकन

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

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

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

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

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

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

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

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

लाभ

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

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

int foo(unsigned char x)
{
     int value = 2147483600; /* assuming 32-bit int and 8-bit char */
     value += x;
     if (value < 2147483600)
        bar();
     return value;
}

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

int foo(unsigned char x)
{
     int value = 2147483600;
     value += x;
     return value;
}

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

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

void run_tasks(unsigned char *ptrx) {
    int z;
    z = foo(*ptrx);
    while (*ptrx > 60) {
        run_one_task(ptrx, z);
    }
}

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

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

अपरिभाषित व्यवहार भी संकलक और स्थैतिक कार्यक्रम विश्लेषण दोनों द्वारा अधिक संकलन-समय की जाँच की अनुमति देता है।[citation needed]

जोखिम

सी और सी ++ मानकों में अपरिभाषित व्यवहार के कई रूप हैं, जो संकलक कार्यान्वयन में वृद्धि की स्वतंत्रता प्रदान करते हैं और वर्तमान में अपरिभाषित रन-टाइम व्यवहार की कीमत पर संकलन-समय की जांच करते हैं। विशेष रूप से, C के लिए मानकीकरण मानक के लिए अंतर्राष्ट्रीय संगठन में अपरिभाषित व्यवहार के सामान्य स्रोतों को सूचीबद्ध करने वाला एक परिशिष्ट है।[4] इसके अतिरिक्त, अपरिभाषित व्यवहार पर निर्भर कोड का निदान करने के लिए संकलक की आवश्यकता नहीं होती है। इसलिए, प्रोग्रामर, यहां तक ​​​​कि अनुभवी लोगों के लिए, अपरिभाषित व्यवहार पर या तो गलती से भरोसा करना आम बात है, या केवल इसलिए कि वे भाषा के नियमों से अच्छी तरह अनुभव नहीं हैं जो सैकड़ों पृष्ठों को फैला सकते हैं। इसका परिणाम उन बगों में हो सकता है जो एक अलग कंपाइलर, या अलग-अलग सेटिंग्स का उपयोग करते समय सामने आते हैं। सक्रिय अपरिभाषित व्यवहार जांच के साथ परीक्षण या फज़िंग सक्षम, उदाहरण के लिए, क्लैंग सैनिटाइज़र, अपरिभाषित व्यवहार को पकड़ने में मदद कर सकता है जो संकलक या स्थिर विश्लेषक द्वारा निदान नहीं किया गया है।[5]

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

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

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

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

एक स्ट्रिंग शाब्दिक को संशोधित करने का प्रयास अपरिभाषित व्यवहार का कारण बनता है:

char *p = "wikipedia"; // valid C, deprecated in C++98/C++03, ill-formed as of C++11
p[0] = 'W'; // undefined behavior

अपरिभाषित व्यवहार में शून्य परिणामों से पूर्णांक विभाजन:Cite error: Invalid <ref> tag; invalid names, e.g. too many C++ 11 के अनुक्रम बिंदुओं के संबंध में अपरिभाषित व्यवहार का कारण बनने में काफी बदलाव हैं।[10] आधुनिक कंपाइलर चेतावनियों का उत्सर्जन कर सकते हैं जब वे एक ही वस्तु में कई अप्रतिबंधित संशोधनों का सामना करते हैं।[11][12] निम्न उदाहरण सी और C ++ दोनों में अपरिभाषित व्यवहार का कारण बनता है।

int f(int i) {
  return i++ + i++; /* undefined behavior: two unsequenced modifications to i */
}

दो अनुक्रम बिंदुओं के बीच किसी वस्तु को संशोधित करते समय, संग्रहित किए जाने वाले मूल्य को निर्धारित करने के अतिरिक्त किसी अन्य उद्देश्य के लिए वस्तु के मूल्य को पढ़ना भी अपरिभाषित व्यवहार है। ). ISO/IEC 9899|ISO/IEC 9899:1999(E): प्रोग्रामिंग लैंग्वेज - C §6.5 एक्सप्रेशंस पैरा। 2</रेफरी>

a[i] = i++; // undefined behavior
printf("%d %d\n", ++n, power(2, n)); // also undefined behavior

C/C++ में तार्किक पारी एक मान को कई बिट्स द्वारा बदलता है जो या तो ऋणात्मक संख्या है या इस मूल्य में बिट्स की कुल संख्या से अधिक या बराबर है, जिसके परिणामस्वरूप अपरिभाषित व्यवहार होता है। सबसे सुरक्षित विधि (संकलक विक्रेता की परवाह किए बिना) हमेशा बिट्स की संख्या को शिफ्ट करने के लिए रखना है (संचालन का सही संचालन) << और >> बिटवाइज़ ऑपरेशन) सीमा के भीतर: <0, sizeof(value)*CHAR_BIT - 1> (जहां value बायां ऑपरेंड है)।

int num = -1;
unsigned int val = 1 << num; //shifting by a negative number - undefined behavior

num = 32; //or whatever number greater than 31
val = 1 << num; //the literal '1' is typed as a 32-bit integer - in this case shifting by more than 31 bits is undefined behavior

num = 64; //or whatever number greater than 63
unsigned long long val2 = 1ULL << num; //the literal '1ULL' is typed as a 64-bit integer - in this case shifting by more than 63 bits is undefined behavior


जंग में उदाहरण

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

fn main() {
    // The following line invokes immediate undefined behaviour.
    let _null_reference: &i32 = unsafe { std::mem::zeroed() };
}

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

यह भी देखें

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

संदर्भ

  1. "नाक के राक्षस". Jargon File. Retrieved 12 June 2014.
  2. GCC Undefined Behavior Sanitizer – ubsan
  3. "A bit of background on compilers exploiting signed overflow".
  4. ISO/IEC 9899:2011 §J.2.
  5. John Regehr. "Undefined behavior in 2017, cppcon 2017". YouTube.
  6. "Vulnerability Note VU#162289 — gcc silently discards some wraparound checks". Vulnerability Notes Database. CERT. 4 April 2008. Archived from the original on 9 April 2008.
  7. Jonathan Corbet (16 April 2008). "जीसीसी और सूचक अतिप्रवाह". Linux Weekly News.
  8. "Vulnerability Note VU#162289 — C compilers may silently discard some wraparound checks". Vulnerability Notes Database. CERT. 8 October 2008 [4 April 2008].
  9. Pascal Cuoq and John Regehr (4 July 2017). "Undefined Behavior in 2017, Embedded in Academia Blog".
  10. "मूल्यांकन का क्रम - cppreference.com". en.cppreference.com. Retrieved 9 August 2016.
  11. "चेतावनी विकल्प (जीएनयू कंपाइलर संग्रह (जीसीसी) का उपयोग करके)". GCC, the GNU Compiler Collection - GNU Project - Free Software Foundation (FSF). Retrieved 2021-07-09.
  12. "क्लैंग में नैदानिक ​​झंडे". Clang 13 documentation. Retrieved 2021-07-09. {{cite web}}: zero width space character in |title= at position 20 (help)
  13. "व्यवहार अपरिभाषित माना जाता है". The Rust Reference. Retrieved 2022-11-28.


अग्रिम पठन


बाहरी संबंध