c++ - अपरिभाषित, अनिर्दिष्ट और कार्यान्वयन-परिभाषित व्यवहार




undefined-behavior c++-faq (6)

आधिकारिक सी तर्क दस्तावेज से

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

अनिर्दिष्ट व्यवहार कार्यान्वयन कार्यक्रमों में अनुवाद करने में कुछ अक्षांश देता है। यह अक्षांश कार्यक्रम का अनुवाद करने में असफल होने तक विस्तारित नहीं होता है।

अपरिभाषित व्यवहार कार्यान्वयन लाइसेंस को कुछ प्रोग्राम त्रुटियों को पकड़ने के लिए देता है जो निदान करना मुश्किल होता है। यह संभावित अनुरूप भाषा विस्तार के क्षेत्रों की भी पहचान करता है: कार्यान्वयन आधिकारिक रूप से अपरिभाषित व्यवहार की परिभाषा प्रदान करके भाषा को बढ़ा सकता है।

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

सी और सी ++ में अपरिभाषित, अनिर्दिष्ट, और कार्यान्वयन-परिभाषित व्यवहार के बीच क्या अंतर है?


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

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

दुर्भाग्यवश, 1 99 0 के मध्य के बाद से कंपाइलर लेखकों ने व्यवहारिक जनादेशों की कमी को एक निर्णय के रूप में समझना शुरू कर दिया है कि व्यवहारिक गारंटीएं उन अनुप्रयोग क्षेत्रों में भी लागत के लायक नहीं हैं जहां वे महत्वपूर्ण हैं, और यहां तक ​​कि उन प्रणालियों पर भी जहां वे व्यावहारिक रूप से कुछ भी लागत नहीं लेते हैं। उचित निर्णय लेने के लिए यूबी के निमंत्रण के रूप में इलाज करने के बजाय, कंपाइलर लेखकों ने इसे ऐसा करने के बहाने के रूप में पेश करना शुरू कर दिया है।

उदाहरण के लिए, निम्नलिखित कोड दिया गया है:

int scaled_velocity(int v, unsigned char pow)
{
  if (v > 250)
    v = 250;
  if (v < -250)
    v = -250;
  return v << pow;
}

एक दो के पूरक कार्यान्वयन को अभिव्यक्ति के इलाज के लिए किसी भी प्रयास को खर्च नहीं करना पड़ेगा v << pow दो के पूरक शिफ्ट के रूप में चाहे v सकारात्मक या नकारात्मक था या नहीं।

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


खैर, यह मूल रूप से मानक से एक सीधी प्रतिलिपि है

3.4.1 1 कार्यान्वयन-परिभाषित व्यवहार अनिर्दिष्ट व्यवहार जहां प्रत्येक कार्यान्वयन दस्तावेज कैसे किया जाता है

2 उदाहरण कार्यान्वयन-परिभाषित व्यवहार का एक उदाहरण हाई-ऑर्डर बिट का प्रचार है जब एक हस्ताक्षरित पूर्णांक सही स्थानांतरित हो जाता है।

3.4.3 1 अपरिभाषित व्यवहार व्यवहार, एक गैर-योग्य या गलत प्रोग्राम निर्माण या गलत डेटा के उपयोग पर, जिसके लिए यह अंतर्राष्ट्रीय मानक कोई आवश्यकता नहीं लगाता है

2 नोट संभावित अपरिभाषित व्यवहार, अप्रत्याशित परिणामों के साथ पूरी तरह से स्थिति को अनदेखा करने से, अनुवाद या निष्पादन को समाप्त करने के लिए पर्यावरण के लक्षण (डायग्नोस्टिक संदेश जारी करने के बिना) के एक दस्तावेज तरीके से अनुवाद या प्रोग्राम निष्पादन के दौरान व्यवहार करने के लिए होता है। एक नैदानिक ​​संदेश जारी करना)।

3 उदाहरण अपरिभाषित व्यवहार का एक उदाहरण पूर्णांक अतिप्रवाह पर व्यवहार है।

3.4.4 अनिर्दिष्ट व्यवहार का अनिर्दिष्ट व्यवहार , या अन्य व्यवहार जहां यह अंतर्राष्ट्रीय मानक दो या दो से अधिक संभावनाएं प्रदान करता है और किसी भी उदाहरण में चुनी गई कोई और आवश्यकता नहीं लगाता है

2 उदाहरण अनिर्दिष्ट व्यवहार का एक उदाहरण वह क्रम है जिसमें किसी फ़ंक्शन के तर्कों का मूल्यांकन किया जाता है।


मानकों की कठोर परिभाषा की तुलना में समझने के लिए शायद आसान शब्द आसान हो सकता है।

कार्यान्वयन-परिभाषित व्यवहार
भाषा कहती है कि हमारे पास डेटा-प्रकार हैं। कंपाइलर विक्रेता निर्दिष्ट करते हैं कि वे किस आकार का उपयोग करेंगे, और उन्होंने जो किया उसके बारे में एक दस्तावेज प्रदान करते हैं।

अपरिभाषित व्यवहार
आप कुछ गलत कर रहे हैं। उदाहरण के लिए, आपके पास एक int में बहुत बड़ा मूल्य है जो char में फिट नहीं होता है। आप उस मान को char में कैसे डालते हैं? वास्तव में कोई रास्ता नहीं है! कुछ भी हो सकता है, लेकिन सबसे समझदार बात उस int के पहले बाइट को लेना और इसे char में रखना होगा। ऐसा करना गलत है कि पहले बाइट को असाइन करना है, लेकिन हुड के नीचे क्या होता है।

अनिर्दिष्ट व्यवहार
इन दोनों का कौन सा कार्य पहले निष्पादित किया गया है?

void fun(int n, int m);

int fun1()
{
  cout << "fun1";
  return 1;
}
int fun2()
{
  cout << "fun2";
  return 2;
}
...
fun(fun1(), fun2()); // which one is executed first?

भाषा मूल्यांकन निर्दिष्ट नहीं करती है, बाएं से दाएं या दाएं से बाएं! तो एक अनिर्धारित व्यवहार एक अपरिभाषित व्यवहार के परिणामस्वरूप हो सकता है या नहीं, लेकिन निश्चित रूप से आपके कार्यक्रम को अनिर्दिष्ट व्यवहार नहीं करना चाहिए।

@eSKay मुझे लगता है कि आपका प्रश्न अधिक स्पष्ट करने के उत्तर को संपादित करने लायक है :)

fun(fun1(), fun2()); व्यवहार "कार्यान्वयन परिभाषित" नहीं है? कंपाइलर को एक या दूसरा कोर्स चुनना है, आखिरकार?

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

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

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


अपरिभाषित व्यवहार बनाम अनिर्धारित व्यवहार का इसका संक्षिप्त विवरण है।

उनका अंतिम सारांश:

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


अपरिभाषित व्यवहार सी और सी ++ भाषा के उन पहलुओं में से एक है जो अन्य भाषाओं से आने वाले प्रोग्रामर के लिए आश्चर्यजनक हो सकता है (अन्य भाषाएं इसे बेहतर तरीके से छिपाने की कोशिश करती हैं)। असल में, सी ++ प्रोग्राम लिखना संभव है जो अनुमानित तरीके से व्यवहार नहीं करते हैं, भले ही कई सी ++ कंपाइलर प्रोग्राम में किसी भी त्रुटि की रिपोर्ट नहीं करेंगे!

चलिए एक क्लासिक उदाहरण देखें:

#include <iostream>

int main()
{
    char* p = "hello!\n";   // yes I know, deprecated conversion
    p[0] = 'y';
    p[5] = 'w';
    std::cout << p;
}

परिवर्तनीय p स्ट्रिंग अक्षर "hello!\n" को इंगित करता है, और नीचे दिए गए दो असाइनमेंट उस स्ट्रिंग को शाब्दिक रूप से संशोधित करने का प्रयास करते हैं। यह कार्यक्रम क्या करता है? सी ++ मानक के खंड 2.14.5 अनुच्छेद 11 के अनुसार, यह अपरिभाषित व्यवहार का आह्वान करता है :

स्ट्रिंग अक्षर को संशोधित करने का प्रयास करने का प्रभाव अपरिभाषित है।

मैं लोगों को चिल्लाना सुन सकता हूं "लेकिन रुको, मैं इसे किसी भी समस्या को संकलित नहीं कर सकता और आउटपुट yellow प्राप्त कर सकता हूं" या "आपका क्या मतलब अपरिभाषित है, स्ट्रिंग अक्षर केवल पढ़ने योग्य स्मृति में संग्रहीत हैं, इसलिए पहले असाइनमेंट प्रयास के परिणामस्वरूप कोर डंप" । यह अनिर्धारित व्यवहार के साथ बिल्कुल समस्या है। असल में, जब आप अपरिभाषित व्यवहार (यहां तक ​​कि नाक राक्षसों) का आह्वान करते हैं तो मानक कुछ भी होने की अनुमति देता है। यदि भाषा के आपके मानसिक मॉडल के अनुसार "सही" व्यवहार है, तो वह मॉडल बस गलत है; सी ++ मानक में एकमात्र वोट, अवधि है।

अपरिभाषित व्यवहार के अन्य उदाहरणों में अपनी सीमाओं से परे एक सरणी का उपयोग करना, शून्य सूचक को संदर्भित करना , अपने जीवनकाल समाप्त होने के बाद वस्तुओं को एक्सेस करना या कथित रूप से चतुर अभिव्यक्तियों को लिखना शामिल है जैसे i++ + ++i

सी ++ मानक की धारा 1.9 में अनिर्धारित व्यवहार के दो कम खतरनाक भाइयों, अनिर्दिष्ट व्यवहार और कार्यान्वयन-परिभाषित व्यवहार का भी उल्लेख है :

इस अंतर्राष्ट्रीय मानक में अर्थपूर्ण विवरण पैरामीटरकृत नोडेटर्मिनिस्टिक सार मशीन को परिभाषित करते हैं।

अमूर्त मशीन के कुछ पहलुओं और संचालन को इस अंतर्राष्ट्रीय मानक में क्रियान्वयन-परिभाषित के रूप में वर्णित किया गया है (उदाहरण के लिए, sizeof(int) )। ये सार मशीन के पैरामीटर का गठन करते हैं। प्रत्येक कार्यान्वयन में इन विशेषताओं में अपनी विशेषताओं और व्यवहार का वर्णन करने वाले दस्तावेज शामिल होंगे।

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

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

विशेष रूप से, खंड 1.3.24 कहता है:

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

अपरिभाषित व्यवहार में भागने से बचने के लिए आप क्या कर सकते हैं? असल में, आपको लेखकों द्वारा अच्छी सी ++ किताबें पढ़नी होंगी जो जानते हैं कि वे किस बारे में बात कर रहे हैं। इंटरनेट ट्यूटोरियल पेंच। स्क्रू bullschildt।





unspecified-behavior