शीर्ष उत्तर गलत (लेकिन सामान्य) गलत धारणा है:
अपरिभाषित व्यवहार एक रन-टाइम प्रॉपर्टी है *। यह "समय-यात्रा" नहीं कर सकता है !
साइड-इफेक्ट के लिए कुछ मानक (मानक द्वारा) परिभाषित किए गए हैं और उन्हें अनुकूलित नहीं किया जा सकता है। ऐसे ऑपरेशन जो I / O करते हैं या जो एक्सेस volatile
वैरिएबल इस श्रेणी में आते हैं।
हालांकि , एक चेतावनी है: यूबी कोई भी व्यवहार हो सकता है, जिसमें व्यवहार शामिल है जो पिछले संचालन को पूर्ववत करता है। इसके कुछ परिणाम हो सकते हैं, कुछ मामलों में, पहले के कोड को अनुकूलित करने के लिए।
वास्तव में, यह शीर्ष उत्तर (जोर मेरा) में उद्धरण के अनुरूप है:
एक अच्छी तरह से गठित कार्यक्रम को क्रियान्वित करने वाला एक अनुरूप कार्यान्वयन एक ही कार्यक्रम और एक ही इनपुट के साथ अमूर्त मशीन के संबंधित उदाहरण के संभावित निष्पादन में से एक के रूप में एक ही नमूदार व्यवहार का उत्पादन करेगा।
हालाँकि, यदि इस तरह के किसी भी निष्पादन में एक अपरिभाषित ऑपरेशन होता है, तो यह अंतर्राष्ट्रीय मानक उस इनपुट के साथ उस प्रोग्राम को निष्पादित करने वाले कार्यान्वयन पर कोई आवश्यकता नहीं रखता है (पहले अपरिभाषित ऑपरेशन से पहले संचालन के संबंध में भी नहीं)।
हाँ, इस उद्धरण करता है का कहना है कि "भी नहीं पहले अपरिभाषित आपरेशन पूर्ववर्ती संचालन के संबंध में" , लेकिन सूचना है कि यह विशेष रूप से के बारे में कोड है कि किया जा रहा है मार डाला , केवल संकलित नहीं।
आखिरकार, अपरिभाषित व्यवहार जो वास्तव में नहीं होता है, वह कुछ भी नहीं करता है, और यूबी युक्त लाइन के लिए वास्तव में पहुंच जाता है, कोड जो इसे पहले निष्पादित करता है!
हां, एक बार यूबी निष्पादित होने के बाद , पिछले ऑपरेशनों का कोई भी प्रभाव अपरिभाषित हो जाता है। लेकिन जब तक ऐसा नहीं होता, तब तक कार्यक्रम का निष्पादन अच्छी तरह से परिभाषित है।
ध्यान दें, हालांकि, इस कार्यक्रम के सभी निष्पादन जो इसके परिणामस्वरूप होते हैं, उन्हें समतुल्य कार्यक्रमों के लिए अनुकूलित किया जा सकता है , जिसमें कोई भी ऐसा कार्य शामिल है जो पिछले ऑपरेशन करता है लेकिन फिर उनके प्रभावों को अन-डू करता है। नतीजतन, पूर्ववर्ती कोड को दूर किया जा सकता है जब भी ऐसा करना उनके प्रभावों के बराबर होगा ; अन्यथा, यह नहीं हो सकता। एक उदाहरण के लिए नीचे देखें।
* नोट: यह संकलन समय पर होने वाले UB के साथ असंगत नहीं है । संकलक वास्तव में साबित कर सकते हैं कि यूबी कोड होगा हमेशा सभी आदानों के लिए क्रियान्वित किया है, तो यूबी संकलन समय के लिए विस्तार कर सकते हैं। हालांकि, यह जानने की आवश्यकता है कि सभी पिछले कोड अंततः लौटते हैं , जो एक मजबूत आवश्यकता है। फिर, एक उदाहरण / स्पष्टीकरण के लिए नीचे देखें।
इस ठोस को बनाने के लिए, ध्यान दें कि निम्न कोड को प्रिंट करना होगा foo
और अपने इनपुट की प्रतीक्षा करनी होगी, जो किसी भी अपरिभाषित व्यवहार की परवाह किए बिना हो।
printf("foo")
getchar()
*(char*)1 = 1
हालांकि, यह भी ध्यान दें कि कोई गारंटी नहीं है कि foo
स्क्रीन पर यूबी होने के बाद भी रहेगा, या आपके द्वारा टाइप किया गया चरित्र अब इनपुट बफर में नहीं होगा; ये दोनों ऑपरेशन "पूर्ववत" हो सकते हैं, जिसका यूबी "टाइम-ट्रैवल" पर समान प्रभाव पड़ता है।
अगर getchar()
लाइन वहाँ नहीं था, यह होगा कानूनी हो लाइनों के लिए दूर करने के लिए अनुकूलित किया जाना यदि और केवल यदि है कि हो सकता है पृथक outputting से foo
यह "गैर-कर" और फिर।
दोनों अविभाज्य होंगे या नहीं यह पूरी तरह कार्यान्वयन (यानी आपके संकलक और मानक पुस्तकालय) पर निर्भर करेगा । उदाहरण के लिए, क्या आउटपुट पढ़ने के लिए किसी अन्य प्रोग्राम की प्रतीक्षा करते हुए आपका धागा यहां अपना printf
ब्लॉक कर सकता है ? या तुरंत लौट आएगा?
यदि यह यहां ब्लॉक कर सकता है, तो एक और कार्यक्रम इसके पूर्ण आउटपुट को पढ़ने से इनकार कर सकता है, और यह कभी वापस नहीं आ सकता है, और परिणामस्वरूप यूबी वास्तव में हो सकता है।
अगर यह तुरंत यहां वापस आ सकता है, तो हमें पता है कि इसे वापस लौटना चाहिए, और इसलिए इसे अनुकूलित करना पूरी तरह से इसे निष्पादित करने से अप्रभेद्य है और फिर इसके प्रभावों को एकजुट करना।
बेशक, चूंकि कंपाइलर जानता है कि उसके विशेष संस्करण के लिए कौन सा व्यवहार स्वीकार्य है printf
, तो वह तदनुसार अनुकूलित कर सकता है, और परिणामस्वरूप printf
कुछ मामलों में अनुकूलित हो सकता है और अन्य नहीं। लेकिन, फिर से, औचित्य यह है कि यह यूबी संयुक्त राष्ट्र के पिछले परिचालन से अप्रभेद्य होगा, यह नहीं कि यूबी के कारण पिछला कोड "जहर" है।
a
नहीं कर सकता है (केवल स्वयं की गणना को छोड़कर) और बस हटा देंa