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


529

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


1
मुझे पूरा यकीन था कि हम इस befor को पा लेंगे, लेकिन मैं इसे नहीं पा सकता। इसे भी देखें: stackoverflow.com/questions/2301372/…
dmckee --- पूर्व-मध्यस्थ ने बिल्ली



1
यहां एक दिलचस्प चर्चा है (अनुभाग "एनेक्स एल और अनिर्धारित व्यवहार")।
ओवेन

जवाबों:


404

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

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

#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", और नीचे दिए गए दो असाइनमेंट उस स्ट्रिंग शाब्दिक को संशोधित करने का प्रयास करते हैं। यह कार्यक्रम क्या करता है? C ++ मानक के खंड 2.14.5 पैरा 11 के अनुसार, यह अपरिभाषित व्यवहार को आमंत्रित करता है :

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

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

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

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

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

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

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

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

विशेष रूप से, धारा 1.3.24 राज्य:

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

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


6
यह एक अजीब तथ्य है जो मर्ज के परिणामस्वरूप होता है कि यह उत्तर केवल C ++ को कवर करता है, लेकिन इस प्रश्न के टैग में सी। सी। में "अपरिभाषित व्यवहार" की एक अलग धारणा है: इसे अभी भी नैदानिक ​​संदेशों को लागू करने की आवश्यकता होगी भले ही व्यवहार भी कहा गया हो कुछ नियम उल्लंघन (अड़चनों का उल्लंघन) के लिए अपरिभाषित होना।
जोहानस शाउब -

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

5
@FredOverflow, एक अच्छा संकलक हमें कोड को संकलित करने की अनुमति क्यों देता है जो अपरिभाषित व्यवहार देता है? वास्तव में क्या अच्छा इस तरह के कोड को संकलित कर सकता है? जब हम अपरिभाषित व्यवहार देते हैं, तो हम सभी अच्छे संकलक हमें एक विशाल लाल चेतावनी संकेत क्यों नहीं देते हैं?
पेसियर

14
@ स्पेसर कुछ चीजें हैं जो संकलित समय पर जांच योग्य नहीं हैं। उदाहरण के लिए यह गारंटी देना हमेशा संभव नहीं होता है कि अशक्त सूचक को कभी भी अस्वीकृत नहीं किया जाता है, लेकिन यह अपरिभाषित है।
टिम सेगिन

4
@Celeritas, अपरिभाषित व्यवहार गैर-नियतात्मक हो सकता है। उदाहरण के लिए, समय से पहले यह जानना असंभव है कि असिंचित मेमोरी की सामग्री क्या होगी, उदा। int f(){int a; return a;}: aफ़ंक्शन कॉल के बीच मूल्य बदल सकता है।
मार्क

96

खैर, यह मूल रूप से मानक से एक सीधे कॉपी-पेस्ट है

३.४.१कार्यान्वयन-परिभाषित व्यवहार अनिर्दिष्ट व्यवहार है जहाँ प्रत्येक कार्यान्वयन दस्तावेज़ को विकल्प कैसे बनाया जाता है

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

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

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

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

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

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


3
कार्यान्वयन-परिभाषित और अनिर्दिष्ट व्यवहार के बीच अंतर क्या है?
ज़ोलोमन

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

1
@Zolomon: यह 3.4.1 और 2.4.4 के बीच के अंतर में परिलक्षित होता है।
sbi

8
@Celeritas: हाइपर-आधुनिक संकलक इससे बेहतर कर सकते हैं। यह देखते हुए int foo(int x) { if (x >= 0) launch_missiles(); return x << 1; }एक संकलक निर्धारित कर सकते हैं कि समारोह है कि अपरिभाषित व्यवहार आह्वान मिसाइलों का शुभारंभ नहीं है लागू की हर तरह से, यह करने के लिए कॉल कर सकते हैं launch_missiles()बिना शर्त।
सुपरकैट

2
@northerner जैसा कि उद्धरण में कहा गया है, अनिर्दिष्ट व्यवहार आमतौर पर संभव व्यवहारों के एक सीमित सेट तक ही सीमित है। कुछ मामलों में आप इस निष्कर्ष पर भी पहुंच सकते हैं कि दिए गए संदर्भ में ये सभी संभावनाएं स्वीकार्य हैं, ऐसे मामलों में अनिर्दिष्ट व्यवहार बिल्कुल भी समस्या नहीं है। अपरिभाषित व्यवहार पूरी तरह से अप्रतिबंधित है (ईब "कार्यक्रम आपकी हार्ड ड्राइव को प्रारूपित करने का निर्णय ले सकता है")। अपरिभाषित व्यवहार हमेशा एक समस्या है।
टीटी

60

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

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

अपरिभाषित व्यवहार
आप कुछ गलत कर रहे हैं। उदाहरण के लिए, आपके पास एक बहुत बड़ा मूल्य है intजो इसमें फिट नहीं है char। आप उस मूल्य को कैसे डालेंगे char? वास्तव में कोई रास्ता नहीं है! कुछ भी हो सकता है, लेकिन सबसे समझदारी वाली बात यह होगी कि उस इंट की पहली बाइट ले लें और उसे डाल दें 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 है। अनिर्दिष्ट व्यवहार के विपरीत, जहां कंपाइलर ठीक कह सकता है कि मैं इन तर्कों का बाएं-से-दाएं मूल्यांकन करने वाला हूं और अगले फ़ंक्शन के तर्कों का दाएं-से-बाएं मूल्यांकन किया जाता है। यह उसी कार्यक्रम में हो सकता है, इसीलिए इसे अनिर्दिष्ट कहा जाता है । वास्तव में, C ++ को आसान बनाया जा सकता था यदि कुछ अनिर्दिष्ट व्यवहार निर्दिष्ट किए जाते। इसके लिए डॉ। स्ट्रॉस्ट्रुप के जवाब पर एक नज़र डालें :

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

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


1
के लिए fun(fun1(), fun2());व्यवहार नहीं है "implementation defined"? संकलक को एक या दूसरे कोर्स को चुनना होगा, आखिर?
लेज़र

1
@ आरा: समझाने के लिए धन्यवाद। मैं अब इसे समझ गया हूं। Btw, "I am gonna evaluate these arguments left-to-right and the next function's arguments are evaluated right-to-left"मुझे यह समझ में आता canहै। क्या यह वास्तव में, संकलक के साथ जो हम इन दिनों का उपयोग करते हैं?
लेज़र

1
@eSKay आपको इस बारे में एक गुरु से पूछना है, जिसने कई संकलक के साथ अपने हाथों को गंदा कर लिया :) AFAIK VC हमेशा दायें-से-बाएँ तर्क का मूल्यांकन करता है।
आरा

4
@ लेज़र: यह निश्चित रूप से हो सकता है। सरल परिदृश्य: फू (बार, बोज़) () और फू (बोज़ (), बार), जहां बार एक इंट और बोज़ है () एक फ़ंक्शन है जो इंट को लौटाता है। एक सीपीयू मान लें जहां पैरामीटर को रजिस्टरों में पास होने की उम्मीद है R0-R1। R0 में फ़ंक्शन परिणाम लौटाए जाते हैं; फ़ंक्शन आर 1 को कचरा कर सकते हैं। "Boz ()" से पहले "बार" का मूल्यांकन करने से पहले boz () को कॉल करने से पहले कहीं और बार की एक प्रति सहेजने की आवश्यकता होगी और फिर उस सहेजी गई प्रतिलिपि को लोड करना होगा। "बोज़ ()" के बाद "बार" का मूल्यांकन करना मेमोरी स्टोर और री-भ्रूण से बचना होगा, और एक अनुकूलन है कई कंपाइलर तर्क सूची में उनके आदेश की परवाह किए बिना करेंगे।
सुपरकाट

6
मुझे C ++ के बारे में पता नहीं है, लेकिन C मानक कहता है कि एक चार्ट में इंट का रूपांतरण या तो कार्यान्वयन परिभाषित है या अच्छी तरह से परिभाषित है (वास्तविक मूल्यों और प्रकारों की हस्ताक्षर पर निर्भर करता है)। C99 .36.3.1.3 (C11 में अपरिवर्तित) देखें।
निकोलाई रुहे

27

आधिकारिक C Rationale दस्तावेज़ से

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

अनिर्दिष्ट व्यवहार कार्यान्वयनकर्ता को अनुवाद करने वाले कार्यक्रमों में कुछ अक्षांश देता है। यह अक्षांश कार्यक्रम का अनुवाद करने में विफल होने के रूप में आगे नहीं बढ़ता है।

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

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


3
हाइपर-आधुनिक संकलक लेखक "अपरिभाषित व्यवहार" को भी मानते हैं क्योंकि संकलक लेखकों को यह मानने के लिए लाइसेंस प्रदान करते हैं कि प्रोग्राम को कभी भी ऐसे इनपुट नहीं मिलेंगे जो अपरिभाषित व्यवहार का कारण बनेंगे, और इस तरह के इनपुटों के दौरान प्रोग्राम कैसे व्यवहार करते हैं, के सभी पहलुओं को मनमाने ढंग से बदल सकते हैं।
सुपरकैट

2
एक अन्य बिंदु जो मैंने अभी देखा है: C89 ने "एक्सटेंशन" शब्द का उपयोग उन विशेषताओं का वर्णन करने के लिए नहीं किया है जो कुछ कार्यान्वयनों पर गारंटी दी गई थीं, लेकिन अन्य नहीं। C89 के लेखकों ने माना कि तत्कालीन वर्तमान कार्यान्वयनों में से अधिकांश पर हस्ताक्षर किए गए अंकगणित और बिना अंकगणित के अंकगणित को पहचाना जाएगा, सिवाय इसके कि जब कुछ निश्चित तरीकों से परिणामों का उपयोग किया गया, और इस तरह के उपचार पर हस्ताक्षर किए गए अतिप्रवाह के मामले में भी लागू किया गया; उन्होंने एनेक्स जे 2 में एक सामान्य विलोपन के रूप में सूचीबद्ध नहीं किया था, हालांकि, जो मुझे बताता है कि उन्होंने इसे विस्तार की बजाय प्राकृतिक मामलों की स्थिति के रूप में देखा।
सुपरकैट

10

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

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

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


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

8

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

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

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

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

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। भले ही नकारात्मक मूल्यों के बाएं-स्थानांतरण को महत्व के हर एक संकलक पर समर्थन किया जाता था, और मौजूदा कोड की एक बड़ी मात्रा उस व्यवहार पर निर्भर करती है, आधुनिक दर्शन इस तथ्य की व्याख्या करेगा कि मानक कहता है कि बाएं-स्थानांतरण नकारात्मक मान यूबी है यह मानते हुए कि संकलक लेखकों को इस बात को अनदेखा करना चाहिए।


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

लेकिन तथ्य यह <<है कि नकारात्मक संख्याओं पर यूबी एक बुरा थोड़ा जाल है और मुझे यह याद दिलाते हुए खुशी हो रही है!
टॉम स्विरली

1
@TomSwirly: दुर्भाग्य से, कंपाइलर लेखकों को इस बात की परवाह नहीं है कि स्टैंडर्ड द्वारा अनिवार्य उन लोगों से परे ढीले व्यवहार की गारंटी देने की पेशकश कर सकते हैं, जो कि कोड द्वारा मानक से परिभाषित कुछ भी नहीं की आवश्यकता है कि कोड से बचने की तुलना में एक बड़े पैमाने पर गति को बढ़ावा दे सकते हैं। यदि कोई प्रोग्रामर यह परवाह नहीं करता है कि क्या i+j>kउन मामलों में 1 या 0 की पैदावार होती है, जहां इसके अतिरिक्त ओवरफ्लो होता है, बशर्ते इसका कोई अन्य दुष्प्रभाव न हो, तो एक कंपाइलर कुछ बड़े पैमाने पर अनुकूलन करने में सक्षम हो सकता है जो कि प्रोग्रामर ने कोड के रूप में लिखा है तो यह संभव नहीं होगा (int)((unsigned)i+j) > k
सुपरकैट

1
@TomSwirly: उनके लिए, यदि कंपाइलर X कुछ कार्य T करने के लिए एक सख्ती से अनुरूप कार्यक्रम ले सकता है और एक निष्पादन योग्य है जो कि कंपाइलर की तुलना में 5% अधिक कुशल है, तो उसी प्रोग्राम के साथ Y उपज प्राप्त करेगा, इसका मतलब है कि X बेहतर है, भले ही Y ऐसा कोड उत्पन्न कर सकता है जिसने एक ही कार्य को तीन बार कुशलतापूर्वक एक प्रोग्राम दिया हो जो ऐसे व्यवहार का शोषण करता है जो Y गारंटी देता है लेकिन X नहीं करता है।
सुपरकैट

6

सी ++ मानक n3337 § 1.3.10 कार्यान्वयन से परिभाषित व्यवहार

व्यवहार, एक सुव्यवस्थित कार्यक्रम निर्माण और सही डेटा के लिए, जो कि कार्यान्वयन और प्रत्येक कार्यान्वयन दस्तावेजों पर निर्भर करता है

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


सी ++ मानक n3337 § 1.3.24 अपरिभाषित व्यवहार

व्यवहार जिसके लिए यह अंतर्राष्ट्रीय मानक कोई आवश्यकता नहीं लगाता है [नोट: यह अंतर्राष्ट्रीय मानक व्यवहार की किसी भी स्पष्ट परिभाषा को छोड़ देता है या जब कोई प्रोग्राम गलत निर्माण या गलत डेटा का उपयोग करता है, तो अपरिभाषित व्यवहार की उम्मीद की जा सकती है। अनुज्ञेय अपरिभाषित व्यवहार की स्थिति की अनदेखी पूरी तरह से अप्रत्याशित परिणामों के साथ होती है, अनुवाद या कार्यक्रम निष्पादन के दौरान व्यवहार करने के लिए पर्यावरण की एक प्रलेखित तरीके से विशेषता (एक नैदानिक ​​संदेश जारी किए बिना या बिना), अनुवाद या निष्पादन को समाप्त करने (जारी करने के साथ)। नैदानिक ​​संदेश का)। कई गलत कार्यक्रम निर्माण अपरिभाषित व्यवहार को प्रस्तुत नहीं करते हैं; उनका निदान किया जाना आवश्यक है। - अंतिम नोट]

जब प्रोग्राम का निर्माण होता है जो C ++ मानक के अनुसार परिभाषित नहीं होता है तो उसे वह करने की अनुमति दी जाती है जो वह करना चाहता है (शायद मुझे एक ईमेल भेजें या शायद आपको एक ईमेल भेजें या शायद कोड को पूरी तरह से अनदेखा करें)।


सी ++ मानक n3337 § 1.3.25 अनिर्दिष्ट व्यवहार

व्यवहार, एक सुव्यवस्थित कार्यक्रम निर्माण और सही डेटा के लिए, जो कार्यान्वयन पर निर्भर करता है [नोट: व्यवहार के लिए कौन सा कार्यान्वयन आवश्यक नहीं है। संभावित व्यवहारों की श्रेणी आमतौर पर इस अंतर्राष्ट्रीय मानक द्वारा चित्रित की जाती है। - अंतिम नोट]

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


6

कार्यान्वयन परिभाषित-

कार्यान्वयन के इच्छुक, अच्छी तरह से प्रलेखित होने चाहिए, मानक विकल्प देता है लेकिन संकलन करना सुनिश्चित करता है

अनिर्दिष्ट -

कार्यान्वयन-परिभाषित के रूप में भी लेकिन दस्तावेज नहीं है

Undefined-

कुछ भी हो सकता है, इसका ख्याल रखें।


2
मुझे लगता है कि यह नोट करना महत्वपूर्ण है कि पिछले कुछ वर्षों में "अपरिभाषित" का व्यावहारिक अर्थ बदल गया है। यह माना जाता है कि दिया गया है uint32_t s;, 1u<<sजब s33 का मूल्यांकन किया जा सकता है , तो शायद 0 या उपज 2 की उम्मीद की जा सकती है, लेकिन कुछ और निराधार नहीं है। नए संकलक, हालांकि, मूल्यांकन 1u<<sकरने से यह निर्धारित करने के लिए एक संकलक हो सकता है कि क्योंकि sपहले से कम 32 होना चाहिए, उस अभिव्यक्ति से पहले या बाद में कोई भी कोड जो केवल प्रासंगिक होगा यदि s32 या उससे अधिक छोड़ा गया हो।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.