पूर्णांक ओवरफ़्लो पर पोर्ट करना एक अच्छा विचार क्यों नहीं है

यह लेख अपरिभाषित व्यवहार और संकलक अनुकूलन पर केंद्रित है, विशेष रूप से हस्ताक्षरित पूर्णांक अतिप्रवाह के संदर्भ में।

अनुवादक से ध्यान दें: रूसी में "रैप" / "रैपिंग" शब्द के उपयोग के संदर्भ में कोई स्पष्ट पत्राचार नहीं है। एक गणितीय शब्द " ट्रांसफर " है, जो वर्णित घटना के करीब है, और शब्द "कैरी फ्लैग" पूर्णांक अतिप्रवाह के दौरान प्रोसेसर में एक ध्वज स्थापित करने के लिए एक तंत्र है। एक अन्य अनुवाद विकल्प "शून्य के आसपास रोटेशन / फ्लिप / क्रांति" वाक्यांश हो सकता है। यह "कैरी" की तुलना में "रैप" के अर्थ को बेहतर ढंग से दर्शाता है, क्योंकि पॉजिटिव से नेगेटिव रेंज में ओवरफ्लो होने पर नंबरों के परिवर्तन को दर्शाता है। हालांकि, जैसा कि यह निकला, ये शब्द परीक्षण पाठकों के लिए पाठ में असामान्य लगते हैं। सरलता के लिए, भविष्य में हम "रैप" शब्द को "रैप" शब्द के अनुवाद के रूप में लेंगे।

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

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

इस कारण से, आप कभी-कभी C में इस कोड को देख सकते हैं:

int b = a + 1000; if (b < a) { //  puts("input too large!"); return; } 

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

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

तो क्या यह गलत है? कोई कहता है कि हाँ, हालाँकि यह स्पष्ट है कि कई संकलक डेवलपर्स इस निर्णय को कानूनी मानते हैं। यदि मैं सही ढंग से समझता हूं, तो अतिप्रवाह के दौरान स्थानांतरण के समर्थकों (संपादित करें: कार्यान्वयन पर निर्भर) के मुख्य तर्क निम्नानुसार हैं:

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

आइए प्रत्येक आइटम को बदले में विश्लेषण करें:

अतिप्रवाह प्रवासन - उपयोगी व्यवहार?

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

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

 if (a > INT_MAX - 1000) { //    puts("input too large!"); return; } int b = a + 1000; 

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

यह सब देखते हुए, मुझे यह तर्क असंबद्ध लगता है कि संक्रमण ज्यादातर मामलों में उपयोगी है।

क्या प्रवासन व्यवहार प्रोग्रामर की अपेक्षा है?

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

समस्या का एक स्पष्ट समाधान (प्रोग्रामर इस व्यवहार की अपेक्षा करते हैं) यह संकलक को चेतावनी देता है जब वह कोड का अनुकूलन करता है, यह मानते हुए कि कोई अपरिभाषित व्यवहार नहीं है। दुर्भाग्य से, जैसा कि हमने ऊपर दिए गए लिंक का उपयोग करके godbolt.org पर उदाहरण में देखा, कंपाइलर हमेशा ऐसा नहीं करते हैं (Gcc संस्करण 7.3 - हां, लेकिन संस्करण 8.1 - नहीं, इसलिए वहां एक कदम पीछे है)।

क्या अनिश्चितकालीन अतिप्रवाह व्यवहार के शब्दार्थ कोई उल्लेखनीय लाभ नहीं देते हैं?

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

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

इसके अलावा, भले ही आप ओवरफ्लो की जांच करते रहें, यह बिल्कुल भी नहीं है कि पूर्णांक चर को स्थानांतरित करने की प्रत्यक्ष लागत अतिरिक्त कोड का उपयोग करने वाली मशीनों पर भी न्यूनतम होगी। उदाहरण के लिए, मिक्स आर्किटेक्चर केवल एक निश्चित आकार (32 बिट्स) के रजिस्टरों में अंकगणितीय ऑपरेशन कर सकता है। एक नियम के रूप में छोटा इंट इंट , 16 बिट्स का आकार है, और चार - 8 बिट्स; जब इन प्रकारों में से एक का एक चर रजिस्टर में संग्रहीत किया जाता है, तो इसका आकार विस्तारित होगा, और इसे सही ढंग से स्थानांतरित करने के लिए, कम से कम एक अतिरिक्त ऑपरेशन करना आवश्यक होगा और, संभवतः, एक अतिरिक्त रजिस्टर का उपयोग करें (संबंधित बिटमास्क को समायोजित करने के लिए)। मुझे यह स्वीकार करना होगा कि मैंने लंबे समय से कूल्हों के लिए कोड के साथ व्यवहार नहीं किया है, इसलिए मुझे इन कार्यों की सटीक लागत के बारे में निश्चित नहीं है, लेकिन मुझे यकीन है कि यह गैर-शून्य है और यही समस्या अन्य आरआईएसआर आर्किटेक्चर पर भी हो सकती है।

क्या भाषा मानक वैरिएबल रैपिंग से परहेज का निषेध करता है यदि यह वास्तुकला से संबंधित है?

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

नोट: अनिर्धारित व्यवहार स्थिति को पूरी तरह से अनदेखा करने का रूप ले सकता है, जबकि परिणाम अप्रत्याशित होगा, ...

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

सबसे पहले, यह ध्यान दिया जाना चाहिए कि यह पाठ "नोट" के रूप में दिया गया है, और इसलिए मानक के लिए परिचय में उल्लिखित आईएसओ निर्देश के अनुसार, आदर्श नहीं है (अर्थात, यह कुछ लिख नहीं सकता है):

आईएसओ / आईईसी निर्देशों के भाग 3 के अनुसार, यह प्रस्तावना, पाठ, नोट्स, फुटनोट्स और उदाहरणों से परिचय केवल सूचनात्मक उद्देश्यों के लिए है।

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

एक असहनीय या गलत सॉफ्टवेयर डिजाइन या गलत डेटा के उपयोग से उत्पन्न होने वाला व्यवहार, जिसके लिए यह अंतर्राष्ट्रीय मानक किसी भी आवश्यकताओं को लागू नहीं करता है

मैंने मुख्य विचार पर प्रकाश डाला: अनिश्चित व्यवहार पर कोई आवश्यकता नहीं लगाई जाती है; नोट में "संभावित प्रकार के अपरिभाषित व्यवहार" की सूची में केवल उदाहरण हैं और अंतिम पर्चे नहीं हो सकते। वाक्यांश "कोई मांग नहीं करता है" अन्यथा व्याख्या नहीं की जा सकती।

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

अंतिम विचार

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

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

सौभाग्य से, संकलक और पोर्टिंग दोनों को कंपाइलर में लागू किया जाता है जो कि मैं सबसे अधिक बार उपयोग करता हूं वह जीसीसी है। मोड के बीच स्विच करने के लिए, -ftrapv और -fwrapv कमांड लाइन तर्क क्रमशः उपयोग किए जाते हैं।

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

अनुपूरक (दिनांक २४ अगस्त २०१ August)

मुझे एहसास हुआ कि उपरोक्त में से बहुत कुछ बेहतर लिखा जा सकता है। नीचे मैं संक्षेप में अपने शब्दों को संक्षेप में समझाता हूं और कुछ छोटी टिप्पणियों को जोड़ता हूं:

  • मैंने यह तर्क नहीं दिया कि अनिश्चित व्यवहार अतिप्रवाह को ले जाने के लिए बेहतर है - बल्कि, व्यवहार में, स्थानांतरण अनिश्चितकालीन व्यवहार से बहुत बेहतर नहीं है। विशेष रूप से, पहले मामले में, और दूसरे में सुरक्षा समस्याएं प्राप्त की जा सकती हैं - और मैं शर्त लगाता हूं कि ओवरफ्लो के कारण होने वाली कई कमजोरियां जो समय पर नहीं पकड़ी गईं (उन लोगों के लिए, जिनके लिए कंपाइलर गलत जांच को हटाने के लिए जिम्मेदार है) - परिणाम के हस्तांतरण के कारण, लेकिन अतिप्रवाह के साथ जुड़े अपरिभाषित व्यवहार के कारण नहीं।
  • हस्तांतरण का एकमात्र वास्तविक लाभ यह है कि अतिप्रवाह चेक हटाए नहीं जाते हैं। हालांकि इस तरह से आप कुछ हमले परिदृश्यों से कोड की रक्षा कर सकते हैं, यह संभावना बनी हुई है कि कुछ ओवरफ्लो की जांच बिल्कुल नहीं की जाएगी (यानी प्रोग्रामर इस तरह के चेक को जोड़ना भूल जाएगा) और किसी का ध्यान नहीं जाएगा।
  • यदि सुरक्षा मुद्दा इतना महत्वपूर्ण नहीं है, और कार्यक्रम की उच्च गति सामने आती है, तो अपरिभाषित व्यवहार अधिक लाभदायक अनुकूलन और उत्पादकता में अधिक वृद्धि, कम से कम कुछ मामलों में देगा। दूसरी ओर, यदि सुरक्षा पहले आती है, तो पोर्टेबिलिटी कमजोरियों से भरा होता है।
  • इसका मतलब यह है कि यदि आप रुकावट, संक्रमण और अपरिभाषित व्यवहार के बीच चयन करते हैं, तो बहुत कम कार्य हैं जिनमें संक्रमण उपयोगी हो सकता है।
  • जैसा कि अतिप्रवाह के लिए जाँच के लिए, मेरा मानना ​​है कि उन्हें छोड़ना हानिकारक है, क्योंकि यह गलत धारणा बनाता है कि वे काम करते हैं और हमेशा काम करेंगे। ओवरफ्लो होने से इस समस्या से बचा जाता है; पर्याप्त चेतावनी - इसे कम करें।
  • मुझे लगता है कि किसी भी डेवलपर को सुरक्षा-महत्वपूर्ण कोड लिखने के लिए आदर्श रूप से उस भाषा के शब्दार्थ की अच्छी कमांड होनी चाहिए जिसमें वह लिखते हैं, साथ ही इसके नुकसान के बारे में भी जानते हैं। सी के लिए, इसका मतलब है कि आपको अतिप्रवाह के शब्दार्थ और अपरिभाषित व्यवहार की सूक्ष्मताओं को जानना होगा। यह दुखद है कि कुछ प्रोग्रामर इस स्तर तक नहीं बढ़े हैं।
  • मैं इस दावे के साथ आया हूं कि "अधिकांश सी प्रोग्रामर डिफ़ॉल्ट व्यवहार के रूप में प्रवासन की उम्मीद करते हैं," लेकिन मुझे इसके लिए सबूत नहीं पता है। (लेख में, मैंने "कुछ प्रोग्रामर" लिखा, क्योंकि मैं वास्तविक जीवन से कई उदाहरण जानता हूं, और सामान्य तौर पर मुझे संदेह है कि कोई भी इसके साथ बहस करेगा)।
  • दो अलग-अलग समस्याएं हैं: सी भाषा मानक की आवश्यकता क्या है और किन कंपाइलरों को लागू करना चाहिए। मैं (आम तौर पर) जिस तरह से मानक अपरिभाषित अतिप्रवाह व्यवहार को परिभाषित करता है। इस पोस्ट में, मैं बात करता हूं कि संकलक को क्या करना चाहिए।
  • जब अतिप्रवाह बाधित होता है, तो इसके लिए हर ऑपरेशन की जांच करने की आवश्यकता नहीं होती है। आदर्श रूप से, इस दृष्टिकोण वाला कार्यक्रम या तो गणितीय नियमों के संदर्भ में लगातार व्यवहार करता है, या काम करना बंद कर देता है। इस मामले में, एक "अस्थायी अतिप्रवाह" का अस्तित्व संभव हो जाता है, जिससे गलत परिणाम की उपस्थिति नहीं होती है। तब दोनों अभिव्यक्ति a + b - b और अभिव्यक्ति (a * b) / b को a के साथ अनुकूलित किया जा सकता है (स्थानांतरण के दौरान पूर्व भी संभव है, लेकिन बाद वाला अब मौजूद नहीं है)।

नोट। लेख का अनुवाद लेखक की अनुमति से ब्लॉग पर प्रकाशित किया गया है। मूल पाठ: डेविन मैक्कल " पूर्णांक ओवरफ्लो पर लपेटें एक अच्छा विचार नहीं है "।

पीवीएस-स्टूडियो टीम से अतिरिक्त संबंधित लिंक:

  1. एंड्री कारपोव। अनिश्चित व्यवहार आपके विचार से अधिक निकट है
  2. विल डिट्ज़, पेंग ली, जॉन रेगर और विक्रम अडवे। C / C ++ में Integer Overflow को समझना
  3. V1026। चर को लूप में बढ़ाया जाता है। हस्ताक्षरित पूर्णांक अतिप्रवाह के मामले में अपरिभाषित व्यवहार होगा
  4. StackOverflow। क्या हस्ताक्षरित पूर्णांक ओवरफ़्लो अभी भी C ++ में अपरिभाषित व्यवहार है?

Source: https://habr.com/ru/post/hi427683/


All Articles