लूप के किस बिंदु पर पूर्णांक ओवरफ़्लो अपरिभाषित व्यवहार बन जाता है?


86

यह मेरे प्रश्न को स्पष्ट करने के लिए एक उदाहरण है जिसमें कुछ अधिक जटिल कोड शामिल हैं जिन्हें मैं यहां पोस्ट नहीं कर सकता।

#include <stdio.h>
int main()
{
    int a = 0;
    for (int i = 0; i < 3; i++)
    {
        printf("Hello\n");
        a = a + 1000000000;
    }
}

इस कार्यक्रम में मेरे मंच पर अपरिभाषित व्यवहार शामिल है क्योंकि a3 लूप पर अतिप्रवाह होगा।

क्या पूरे कार्यक्रम में अपरिभाषित व्यवहार होता है, या केवल अतिप्रवाह के बाद ही वास्तव में ऐसा होता है ? संकलक संभावित रूप से काम कर सकता है जो अतिप्रवाह a करेगा इसलिए यह पूरे लूप को अपरिभाषित घोषित कर सकता है और ओवरफ्लो होने से पहले भी प्रिंटआउट चलाने के लिए परेशान नहीं करता है?

(सी और सी ++ टैग किए गए भले ही अलग-अलग हैं क्योंकि मैं दोनों भाषाओं के जवाबों में रुचि रखता हूं अगर वे अलग हैं।)


7
आश्चर्य है कि यदि कंपाइलर काम aनहीं कर सकता है (केवल स्वयं की गणना को छोड़कर) और बस हटा देंa
4386427

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



जवाबों:


108

यदि आप विशुद्ध रूप से सैद्धांतिक उत्तर में रुचि रखते हैं, तो C ++ मानक "समय यात्रा" के लिए अपरिभाषित व्यवहार की अनुमति देता है:

[intro.execution]/5: एक अच्छी तरह से गठित कार्यक्रम को क्रियान्वित करने वाला एक अनुरूप कार्यान्वयन एक ही कार्यक्रम और एक ही इनपुट के साथ अमूर्त मशीन के संगत उदाहरण के संभावित निष्पादन में से एक के रूप में एक ही अवलोकन व्यवहार का उत्पादन करेगा। हालाँकि, यदि इस तरह के किसी भी निष्पादन में अपरिभाषित ऑपरेशन होता है, तो यह अंतर्राष्ट्रीय मानक उस इनपुट के साथ उस प्रोग्राम को निष्पादित करने वाले कार्यान्वयन पर कोई आवश्यकता नहीं रखता है (पहले अपरिभाषित ऑपरेशन से पहले संचालन के संबंध में भी नहीं)

जैसे, यदि आपके कार्यक्रम में अपरिभाषित व्यवहार है, तो आपके पूरे कार्यक्रम का व्यवहार अपरिभाषित है।


4
@KeithThompson: लेकिन फिर भी, sneeze()फ़ंक्शन खुद को कक्षा की किसी भी चीज़ पर अपरिभाषित करता है Demon(जिसमें से नाक की विविधता एक उपवर्ग है), जो पूरी चीज को गोलाकार बनाती है।
सेबस्टियन लेनार्टोविज़

1
लेकिन प्रिंटफ वापस नहीं आ सकता है, इसलिए पहले दो राउंड को परिभाषित किया गया है क्योंकि जब तक ऐसा नहीं किया जाता है तब तक यह स्पष्ट नहीं है कि वहां कभी यूबी होगा। देखें stackoverflow.com/questions/23153445/...
usr

1
यही कारण है कि तकनीकी रूप से लिनक्स कर्नेल के लिए "एनओपी" का उत्सर्जन करने के अपने अधिकारों के भीतर एक संकलक है (क्योंकि बूटस्ट्रैप कोड अपरिभाषित व्यवहार पर निर्भर करता है): blog.regehr.org/archives/761
क्रैशऑक्ट

3
@ क्रैटरवर्क और यही कारण है कि लिनक्स में लिखा गया है, और के रूप में संकलित किया गया है, असंगत सी (यानी सी का एक सुपरसेट जिसमें विशेष ऑपशन के साथ एक विशेष संकलक की आवश्यकता होती है, जैसे कि -फेनो-सख्त-अलियासिंग)
user375751

3
@usr मुझे उम्मीद है कि अगर printfयह वापस नहीं आता है तो इसे परिभाषित किया जाता है , लेकिन यदि printfयह वापस लौटने वाला है, तो अपरिभाषित व्यवहार से पहले समस्या हो सकती है printf। इसलिए, समय यात्रा। printf("Hello\n");और फिर अगली पंक्ति के रूप में संकलित हैundoPrintf(); launchNuclearMissiles();
user253751

31

पहले, मुझे इस प्रश्न का शीर्षक सही करने दें:

अपरिभाषित व्यवहार निष्पादन के दायरे का (विशेष रूप से) नहीं है।

अनिर्धारित व्यवहार सभी चरणों को प्रभावित करता है: संकलन, लिंकिंग, लोडिंग और निष्पादन।

इसे सीमेंट करने के लिए कुछ उदाहरण, यह ध्यान में रखते हैं कि कोई भी भाग संपूर्ण नहीं है:

  • संकलक मान सकते हैं कि कोड के अंश जिसमें अपरिभाषित व्यवहार शामिल नहीं है, और इस प्रकार निष्पादन पथ जो उन्हें ले जाएंगे मृत कोड हैं। देखें कि हर सी प्रोग्रामर को क्रिस लट्टनर के अलावा किसी और के द्वारा अपरिभाषित व्यवहार के बारे में पता होना चाहिए
  • लिंकर मान सकता है कि एक कमजोर प्रतीक (नाम से मान्यता प्राप्त) की कई परिभाषाओं की उपस्थिति में, सभी परिभाषाएं एक परिभाषा नियम के समान हैं।
  • लोडर (यदि आप डायनेमिक लाइब्रेरीज़ का उपयोग करते हैं तो) समान मान सकते हैं, इस प्रकार यह पहला प्रतीक उठाता है; यह आमतौर पर (ab) LD_PRELOADयूनिक्स पर चाल का उपयोग कर कॉल को इंटरसेप्ट करने के लिए उपयोग किया जाता है
  • निष्पादन विफल हो सकता है (SIGSEV) आपको झूलने वाले बिंदुओं का उपयोग करना चाहिए

अनिर्धारित व्यवहार के बारे में यह इतना डरावना है : यह भविष्यवाणी करना असंभव है, समय से पहले, सटीक व्यवहार क्या होगा, और इस भविष्यवाणी को टूलकिन के प्रत्येक अद्यतन पर फिर से विचार करना होगा, अंतर्निहित ओएस, ...


मैं माइकल स्पेंसर (LLVM डेवलपर) द्वारा इस वीडियो को देखने की सलाह देता हूं: CppCon 2016: माई लिटिल ऑप्टिमाइज़र: अनिर्धारित व्यवहार मैजिक है


3
यही मेरी चिंता है। मेरे वास्तविक कोड में, यह जटिल है लेकिन मेरे पास एक ऐसा मामला हो सकता है जहां यह हमेशा बह निकलेगा। और मैं वास्तव में इस बारे में परवाह नहीं करता, लेकिन मुझे चिंता है कि "सही" कोड भी इससे प्रभावित होगा। जाहिर है मुझे इसे ठीक करने की आवश्यकता है, लेकिन फिक्सिंग के लिए समझ की आवश्यकता है :)
jcoder

8
@jcoder: यहाँ एक महत्वपूर्ण पलायन है। संकलक को इनपुट डेटा पर अनुमान लगाने की अनुमति नहीं है। जब तक कम से कम एक इनपुट है जिसके लिए अनफाइंड बिहेवियर नहीं होता है, कंपाइलर को यह सुनिश्चित करना चाहिए कि यह विशेष इनपुट अभी भी सही आउटपुट का उत्पादन करता है। खतरनाक अनुकूलन के बारे में सभी डरावनी बातें केवल अपरिहार्य यूबी पर लागू होती हैं । व्यावहारिक रूप से, यदि आप argcलूप काउंट के रूप में उपयोग करते हैं, तो मामला argc=1यूबी का उत्पादन नहीं करता है और संकलक को संभालने के लिए मजबूर किया जाएगा।
एमएसल्टर्स

@jcoder: इस मामले में, यह मृत कोड नहीं है। कंपाइलर, हालांकि, यह समझने के लिए पर्याप्त स्मार्ट हो सकता है कि समय iसे अधिक वेतन वृद्धि नहीं की जा सकती है Nऔर इसलिए इसका मूल्य बाध्य है।
मैथ्यू एम।

4
@ जोकर: यदि f(good);कोई चीज X f(bad);करता है और अपरिभाषित व्यवहार को आमंत्रित करता है, तो एक प्रोग्राम जो सिर्फ आह्वान करता f(good);है, वह X करने की गारंटी देता है, लेकिन X f(good); f(bad);करने की गारंटी नहीं है।

4
@Huryl अधिक दिलचस्प है, अगर आपका कोड है if(foo) f(good); else f(bad);, तो एक स्मार्ट कंपाइलर तुलना और उत्पादन और बिना शर्त के दूर फेंक देगा foo(good)
जॉन ड्वोरक

28

एक आक्रामक रूप से सी या सी ++ संकलक को 16 बिट लक्षित करने intसे पता चलेगा कि 1000000000एक intप्रकार को जोड़ने का व्यवहार अपरिभाषित है

किसी भी मानक को ऐसा करने की अनुमति है जो वह चाहता है जिसमें पूरे कार्यक्रम को हटा दिया जाना शामिल हो सकता हैint main(){}

लेकिन बड़े intएस का क्या ? मैं एक कंपाइलर के बारे में नहीं जानता जो यह अभी तक करता है (और मैं किसी भी तरह से C और C ++ कंपाइलर डिज़ाइन का विशेषज्ञ नहीं हूं), लेकिन मुझे लगता है कि कुछ समय में 32 बिट intया उससे अधिक का टारगेट करने वाला कंपाइलर यह पता लगा लेगा कि लूप अनंत है ( iनहीं बदलता है) और इसलिए aअंततः अतिप्रवाह होगा। तो एक बार फिर, यह आउटपुट को ऑप्टिमाइज़ कर सकता है int main(){}। यहाँ मैं जो बात करने की कोशिश कर रहा हूँ वह यह है कि जैसे-जैसे कंपाइलर ऑप्टिमाइज़ेशन उत्तरोत्तर अधिक आक्रामक होते जाते हैं, अधिक से अधिक अपरिभाषित व्यवहार निर्माण खुद को अप्रत्याशित तरीके से प्रकट कर रहे हैं।

यह तथ्य कि आपका लूप अनंत है, लूप बॉडी में मानक आउटपुट के लिए लिखने के बाद से आप स्वयं में अपरिभाषित नहीं हैं।


3
क्या इसे अपरिभाषित व्यवहार के प्रकट होने से पहले ही मानक कुछ भी करने की अनुमति देता है? यह कहाँ बताया गया है?
जिमीफिकी

4
16 बिट क्यों? मुझे लगता है कि ओपी एक 32 बिट हस्ताक्षरित अतिप्रवाह की तलाश कर रहा है।
4386427

8
@jimifiki मानक में। C ++ 14 (N4140) 1.3.24 "udnefined व्यवहार = व्यवहार जिसके लिए यह अंतर्राष्ट्रीय मानक कोई आवश्यकता नहीं है।" साथ ही एक लंबा नोट जो विस्तृत है। लेकिन मुद्दा यह है कि यह एक "बयान" का व्यवहार नहीं है जो अपरिभाषित है, यह कार्यक्रम का व्यवहार है इसका मतलब है कि जब तक यूबी मानक (या एक नियम की अनुपस्थिति) में एक नियम द्वारा ट्रिगर किया जाता है, मानक पूरे के रूप में कार्यक्रम के लिए आवेदन करना बंद कर देता है इसलिए कार्यक्रम का कोई भी भाग व्यवहार कर सकता है।
Angew को अब SO

5
पहला बयान गलत है। यदि int16-बिट है, तो जोड़ इसमें होगा long(क्योंकि शाब्दिक संचालक प्रकार है long) जहां यह अच्छी तरह से परिभाषित है, फिर एक कार्यान्वयन-परिभाषित रूपांतरण द्वारा वापस परिवर्तित किया जाएगा int
आर .. गिटहब स्टॉप हेल्पिंग ICE

2
@usr का व्यवहार printfमानक द्वारा हमेशा लौटने के लिए परिभाषित किया गया है
एमएम

11

तकनीकी रूप से, C ++ मानक के तहत, यदि किसी कार्यक्रम में अपरिभाषित व्यवहार होता है, तो पूरे कार्यक्रम का व्यवहार, यहां तक ​​कि संकलन समय पर (कार्यक्रम से पहले ही निष्पादित किया जाता है) अपरिभाषित होता है।

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

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


यदि यूबी भाग एक if(false) {}दायरे में है तो क्या होगा ? क्या उस पूरे कार्यक्रम में जहर होता है, जिसके कारण संकलक के अनुसार सभी शाखाओं में तर्क के ~ अच्छी तरह से परिभाषित अंश होते हैं, और इस तरह गलत धारणाओं पर काम होता है?
mlvljr

1
मानक अपरिभाषित व्यवहार पर कोई आवश्यकता नहीं डालता है, इसलिए सिद्धांत रूप में , हाँ, यह पूरे कार्यक्रम को जहर देता है। हालांकि, व्यवहार में , किसी भी अनुकूलन कंपाइलर की संभावना केवल मृत कोड को हटा देगी, इसलिए संभवतः इसका निष्पादन पर कोई प्रभाव नहीं पड़ेगा। आप अभी भी इस व्यवहार पर भरोसा नहीं करना चाहिए, हालांकि।
bwDraco

जानकर अच्छा लगा,
धन्यवाद

9

यह समझने के लिए कि अपरिभाषित व्यवहार 'टाइम ट्रैवल' को @TartanLlama के रूप में पर्याप्त रूप से क्यों डाल सकता है , आइए एक नजर डालते हैं 'as-if' नियम पर:

1.9 कार्यक्रम का निष्पादन

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

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

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

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

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


6

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


6

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

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

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

if (currentPtr + numberOfNewChars > endOfBufferPtr) { doOverflowLogic(); }

यह पर्याप्त समझदार है। हालांकि, क्या होगा अगर नंबरऑफनेचर्स वास्तव में बड़ा है, और ओवरफ्लो है? तब यह चारों ओर से घूमता है और एक सूचक से छोटा हो जाता है endOfBufferPtr, इसलिए अतिप्रवाह तर्क कभी नहीं कहा जाएगा। तो उन्होंने इससे पहले एक दूसरा चेक जोड़ा:

if (currentPtr + numberOfNewChars < currentPtr) { detectWrapAround(); }

ऐसा लगता है कि आपने बफर अतिप्रवाह त्रुटि का ध्यान रखा है, है ना? हालाँकि, एक बग यह बताते हुए प्रस्तुत किया गया था कि यह बफ़र डेबियन के एक विशेष संस्करण पर बह निकला! सावधानीपूर्वक जांच से पता चला कि डेबियन का यह संस्करण विशेष रूप से जीसीसी के रक्तस्रावी-किनारे संस्करण का उपयोग करने वाला पहला था। Gcc के इस संस्करण में, कंपाइलर ने माना कि currentPtr + numberOfNewChars , currentPtr से छोटा पॉइंटर कभी नहीं हो सकता क्योंकि पॉइंटर्स के लिए अतिप्रवाह अपरिभाषित व्यवहार है! यह संपूर्ण जांच को अनुकूलित करने के लिए gcc के लिए पर्याप्त था, और अचानक आपने बफर ओवरफ्लो के खिलाफ सुरक्षा नहीं की, भले ही आपने इसे जांचने के लिए कोड लिखा हो!

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


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

बेशक, सही जाँच होगी if(numberOfNewChars > endOfBufferPtr - currentPtr), बशर्ते कि नंबरऑनक्वायर्स कभी भी नकारात्मक नहीं हो सकते हैं और करंटपार्ट हमेशा बफर के भीतर कहीं न कहीं इशारा करता है कि आपको हास्यास्पद "रैपराउंड" चेक की भी ज़रूरत नहीं है। (मुझे नहीं लगता कि आपके द्वारा प्रदान किया गया कोड किसी परिपत्र बफ़र में काम करने की कोई आशा रखता है - आपने
पैराफ्रेज़

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

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

4

सैद्धांतिक जवाबों से परे, एक व्यावहारिक अवलोकन यह होगा कि लंबे समय तक कंपाइलरों ने छोरों पर विभिन्न परिवर्तनों को लागू किया है ताकि उनके भीतर काम की मात्रा कम हो सके। उदाहरण के लिए, दिया गया:

for (int i=0; i<n; i++)
  foo[i] = i*scale;

एक संकलक उस में बदल सकता है:

int temp = 0;
for (int i=0; i<n; i++)
{
  foo[i] = temp;
  temp+=scale;
}

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

if (n > 0)
{
  int temp1 = n*scale;
  int *temp2 = foo;
  do
  {
    temp1 -= scale;
    *temp2++ = temp1;
  } while(temp1);
}

अतिप्रवाह पर मूक आवरण के साथ मशीनों पर भी, यदि खराबी n से कम संख्या होती है, जो कि जब स्केल से गुणा की जाती है, तो उपज होगी 0. यह एक अंतहीन लूप में बदल सकता है यदि पैमाना एक से अधिक बार मेमोरी से पढ़ा जाता है और कुछ अपने मूल्य को अप्रत्याशित रूप से बदल दिया (किसी भी मामले में जहां "स्केल" यूबी को लागू किए बिना मध्य-लूप को बदल सकता है, एक संकलक को अनुकूलन करने की अनुमति नहीं दी जाएगी)।

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


4

अपरिभाषित व्यवहार, परिभाषा के अनुसार, एक ग्रे क्षेत्र है। आप बस यह अनुमान नहीं लगा सकते हैं कि यह क्या करेगा या क्या नहीं करेगा - यही "अपरिभाषित व्यवहार" का अर्थ है

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

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


और फिर भी, यहाँ की बात है ... संकलक अनुकूलन करने के लिए अपरिभाषित व्यवहार का उपयोग कर सकते हैं, लेकिन वे सामान्य रूप से आपको प्रभावित नहीं करेंगे। इसलिए यदि हमारे पास यह भयानक उपकरण है जिसे आपको हर कीमत पर एक्स करने से बचना है, तो कंपाइलर आपको चेतावनी क्यों नहीं दे सकता है ताकि आप इसे ठीक कर सकें?
जेसन एस

1

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

हालाँकि निश्चित रूप से यह स्वयं अपरिभाषित है, क्योंकि अनुकूलन अपरिभाषित है। :)


1
व्यवहार के अपरिभाषित होने का निर्धारण करते समय अनुकूलन पर विचार करने का कोई कारण नहीं है।
कीथ थॉम्पसन

2
तथ्य यह है कि कार्यक्रम व्यवहार करता है क्योंकि कोई यह मान सकता है कि इसका अपरिभाषित व्यवहार "लुप्त" नहीं होना चाहिए। व्यवहार अभी भी अपरिभाषित है और आप बस भाग्य पर भरोसा कर रहे हैं। तथ्य यह है कि संकलक विकल्पों के आधार पर कार्यक्रम का व्यवहार बदल सकता है एक मजबूत संकेतक है कि व्यवहार अपरिभाषित है।
जॉर्डन मेलो

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

@KeithThompson ज़रूर, लेकिन ओपी ने विशेष रूप से अनुकूलन के बारे में पूछा और अपरिभाषित व्यवहार पर इसके प्रभाव के बारे में उन्होंने अपने मंच पर देखा। अनुकूलन के आधार पर वह विशिष्ट व्यवहार लुप्त हो सकता है। जैसा कि मैंने अपने जवाब में कहा है, हालांकि अपरिभाषित नहीं होगा।
ग्राहम

0

चूँकि यह प्रश्न C और C ++ का दोहरा टैग है, इसलिए मैं कोशिश करूँगा और दोनों को संबोधित करूँगा। C और C ++ यहां अलग-अलग दृष्टिकोण अपनाते हैं।

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

हम इसे दोष रिपोर्ट 109 से देख सकते हैं जो इसके क्रूस पर पूछता है:

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

int array1[5];
int array2[5];
int *p1 = &array1[0];
int *p2 = &array2[0];

int foo()
{
int i;
i = (p1 > p2); /* Must this be "successfully translated"? */
1/0; /* Must this be "successfully translated"? */
return 0;
}

तो नीचे पंक्ति सवाल यह है: उपरोक्त कोड "सफलतापूर्वक अनुवादित" होना चाहिए (जो भी इसका मतलब है)? (उपखंड 5.1.1.3 से जुड़े फुटनोट देखें।)

और प्रतिक्रिया थी:

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

C ++ में दृष्टिकोण अधिक आराम से लगता है और यह सुझाव देगा कि एक कार्यक्रम में अपरिभाषित व्यवहार होता है, भले ही कार्यान्वयन इसे वैधानिक रूप से सिद्ध कर सके या नहीं।

हमारे पास [intro.abstrac] p5 है जो कहता है:

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


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

@ सुपरकैट मेरा मानना ​​है कि सी के लिए मेरा जवाब हमें यही कह रहा है।
शफीक यघमौर

मुझे लगता है कि उद्धृत पाठ पुनः C ++ के लिए भी यही लागू होता है, क्योंकि वाक्यांश "कोई भी ऐसा निष्पादन" उन तरीकों को संदर्भित करता है जो प्रोग्राम किसी विशेष दिए गए इनपुट के साथ निष्पादित कर सकता है। यदि कोई विशेष इनपुट फ़ंक्शन को निष्पादित नहीं कर सकता है, तो मुझे यह कहने के लिए उद्धृत पाठ में कुछ भी नहीं दिखता है कि इस तरह के फ़ंक्शन में कुछ भी यूबी में परिणाम होगा।
सुपरकट

-2

शीर्ष उत्तर गलत (लेकिन सामान्य) गलत धारणा है:

अपरिभाषित व्यवहार एक रन-टाइम प्रॉपर्टी है *। यह "समय-यात्रा" नहीं कर सकता है !

साइड-इफेक्ट के लिए कुछ मानक (मानक द्वारा) परिभाषित किए गए हैं और उन्हें अनुकूलित नहीं किया जा सकता है। ऐसे ऑपरेशन जो I / O करते हैं या जो एक्सेस volatileवैरिएबल इस श्रेणी में आते हैं।

हालांकि , एक चेतावनी है: यूबी कोई भी व्यवहार हो सकता है, जिसमें व्यवहार शामिल है जो पिछले संचालन को पूर्ववत करता है। इसके कुछ परिणाम हो सकते हैं, कुछ मामलों में, पहले के कोड को अनुकूलित करने के लिए।

वास्तव में, यह शीर्ष उत्तर (जोर मेरा) में उद्धरण के अनुरूप है:

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

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

हां, एक बार यूबी निष्पादित होने के बाद , पिछले ऑपरेशनों का कोई भी प्रभाव अपरिभाषित हो जाता है। लेकिन जब तक ऐसा नहीं होता, तब तक कार्यक्रम का निष्पादन अच्छी तरह से परिभाषित है।

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

* नोट: यह संकलन समय पर होने वाले UB के साथ असंगत नहीं है । संकलक वास्तव में साबित कर सकते हैं कि यूबी कोड होगा हमेशा सभी आदानों के लिए क्रियान्वित किया है, तो यूबी संकलन समय के लिए विस्तार कर सकते हैं। हालांकि, यह जानने की आवश्यकता है कि सभी पिछले कोड अंततः लौटते हैं , जो एक मजबूत आवश्यकता है। फिर, एक उदाहरण / स्पष्टीकरण के लिए नीचे देखें।


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

printf("foo");
getchar();
*(char*)1 = 1;

हालांकि, यह भी ध्यान दें कि कोई गारंटी नहीं है कि fooस्क्रीन पर यूबी होने के बाद भी रहेगा, या आपके द्वारा टाइप किया गया चरित्र अब इनपुट बफर में नहीं होगा; ये दोनों ऑपरेशन "पूर्ववत" हो सकते हैं, जिसका यूबी "टाइम-ट्रैवल" पर समान प्रभाव पड़ता है।

अगर getchar()लाइन वहाँ नहीं था, यह होगा कानूनी हो लाइनों के लिए दूर करने के लिए अनुकूलित किया जाना यदि और केवल यदि है कि हो सकता है पृथक outputting से fooयह "गैर-कर" और फिर।

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

  • यदि यह यहां ब्लॉक कर सकता है, तो एक और कार्यक्रम इसके पूर्ण आउटपुट को पढ़ने से इनकार कर सकता है, और यह कभी वापस नहीं आ सकता है, और परिणामस्वरूप यूबी वास्तव में हो सकता है।

  • अगर यह तुरंत यहां वापस आ सकता है, तो हमें पता है कि इसे वापस लौटना चाहिए, और इसलिए इसे अनुकूलित करना पूरी तरह से इसे निष्पादित करने से अप्रभेद्य है और फिर इसके प्रभावों को एकजुट करना।

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


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

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

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

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

2
... एक 300-बॉड टर्मिनल को वितरित किया गया था, और इससे पहले होने वाला कोई भी नियंत्रण-सी, गेटचार्ज () का संकेत देगा, भले ही संकेत हो कि बफर में अन्य वर्ण पहले से मौजूद थे, तो ऐसा कार्यान्वयन नहीं हो सकता पिछले आउटपुट को गेटच () से पहले किसी भी यूबी से आगे बढ़ाएं। क्या मुश्किल यह जान रहा है कि किस संकलक को प्रोग्रामर के माध्यम से पारित करने की उम्मीद की जानी चाहिए, कोई भी व्यवहारिक गारंटी देता है कि एक पुस्तकालय कार्यान्वयन जो मानक द्वारा अनिवार्य है उससे परे की पेशकश कर सकता है।
सुपरकट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.