निम्नलिखित कोड मेरे सिस्टम पर अजीब चीजें पैदा करता है:

#include <stdio.h>

void f (int x) {
  int y = x + x;
  int v = !y;
  if (x == (1 << 31))
    printf ("y: %d, !y: %d\n", y, !y);
}

int main () {
  f (1 << 31);
  return 0;
}

-O1 के साथ संकलित, यह y: 0, !y: 0 प्रिंट करता है।

अब इस गूढ़ तथ्य से परे कि int v या if लाइनों को हटाने से अपेक्षित परिणाम मिलते हैं, मैं तार्किक असंगतता में अनुवाद करने वाले अतिप्रवाह के अपरिभाषित व्यवहार से सहज नहीं हूं।

क्या इसे एक बग माना जाना चाहिए, या जीसीसी टीम का दर्शन है कि एक अप्रत्याशित व्यवहार तार्किक विरोधाभास में बदल सकता है?

0
Michaël 22 जिंदा 2020, 03:07
5
तो आप अपरिभाषित व्यवहार के तार्किक/परिभाषित व्यवहार की अपेक्षा कर रहे हैं? यदि व्यवहार अपरिभाषित है gcc वह जो चाहे कर सकता है।
 – 
kaylum
22 जिंदा 2020, 03:11
@kaylum: मैं ऊपर y की गणना के लिए अपरिभाषित व्यवहार को स्थानीयकृत करने की उम्मीद कर रहा हूं, और बाकी सामान्य रूप से व्यवहार करेंगे, उस मूल्य को देखते हुए .; मेरा प्रश्न वास्तव में था कि क्या यह मामला था।
 – 
Michaël
22 जिंदा 2020, 19:44

3 जवाब

सबसे बढ़िया उत्तर

अपरिभाषित व्यवहार लागू करते समय, कुछ भी हो सकता है। एक कारण है कि इसे अपरिभाषित व्यवहार क्यों कहा जाता है।

क्या इसे एक बग माना जाना चाहिए, या जीसीसी टीम का दर्शन है कि एक अप्रत्याशित व्यवहार तार्किक विरोधाभास में बदल सकता है?

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

जैसा कि मैंने मेरा एक अन्य उत्तर में कहा था:

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

7
Marco Bonelli 24 फरवरी 2020, 16:33
1
धन्यवाद, समझ गया: अप्रत्याशित व्यवहार उस अभिव्यक्ति तक सीमित नहीं हैं जहां वे होते हैं।
 – 
Michaël
22 जिंदा 2020, 19:47
मानक के लेखकों ने अपरिभाषित व्यवहार के बारे में कहा, "यह संभावित अनुरूप भाषा विस्तार के क्षेत्रों की भी पहचान करता है: कार्यान्वयनकर्ता आधिकारिक रूप से अपरिभाषित व्यवहार की परिभाषा प्रदान करके भाषा को बढ़ा सकता है"।
 – 
supercat
23 जिंदा 2020, 06:10

2018 सी मानक परिभाषित करता है, खंड 3.4.3, पैराग्राफ 1 में, "अपरिभाषित व्यवहार" होना चाहिए:

व्यवहार, एक गैर-पोर्टेबल या गलत प्रोग्राम निर्माण या गलत डेटा के उपयोग पर, जिसके लिए यह दस्तावेज़ कोई आवश्यकता नहीं लगाता है

यह काफी सरल है। मानक से कोई आवश्यकता नहीं है। इसलिए, नहीं, मानक को व्यवहार के "सुसंगत" होने की आवश्यकता नहीं है। कोई आवश्यकता नहीं है।

इसके अलावा, कंपाइलर, ऑपरेटिंग सिस्टम, और प्रोग्राम बनाने और चलाने में शामिल अन्य चीजें आम तौर पर इस प्रश्न में पूछे गए अर्थ में "संगति" की कोई आवश्यकता नहीं लागू करती हैं।

परिशिष्ट

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

3
Community 20 जून 2020, 12:12
आप जो कहते हैं वह उन कंपाइलरों के बारे में सच है जो सी मानक के लेखकों के इरादे का सम्मान करते हैं, लेकिन न तो जीसीसी और न ही क्लैंग के बारे में सच है।
 – 
supercat
22 फरवरी 2020, 04:27
2
@supercat: ऐसा कोई तरीका नहीं है जिसमें कोई सी कार्यान्वयन या सी "वानाबे" कार्यान्वयन या कोई सॉफ़्टवेयर या कोई हाथी अपरिभाषित व्यवहार के लिए सी मानक की आवश्यकताओं के अनुरूप विफल हो सकता है, अर्थात् कोई आवश्यकता नहीं है।
 – 
Eric Postpischil
22 फरवरी 2020, 05:50
@EricPostpischil: मानक वास्तव में इस बात पर कोई आवश्यकता नहीं लगाता है कि कोई कार्यान्वयन किसी भी प्रोग्राम को कैसे संसाधित करता है जो मानक में दी गई अनुवाद सीमाओं का प्रयोग नहीं करता है। यदि कोई कार्यान्वयन कम से कम एक प्रोग्राम को सही ढंग से संसाधित नहीं करता है जो अनुवाद सीमाओं का प्रयोग करता है, तो यह गैर-अनुरूप है; यदि यह सीमाओं का प्रयोग करने वाले कम से कम एक प्रोग्राम को सही ढंग से संसाधित करता है, तो मानक इस बात पर कोई आवश्यकता नहीं लगाता है कि यह किसी अन्य चीज़ को कैसे संसाधित करता है।
 – 
supercat
22 फरवरी 2020, 09:02
@EricPostpischil: इसके अलावा, मेरा मुद्दा यह था कि क्लैंग और जीसीसी के लेखकों को यूबी के परिणामों को उन लोगों तक सीमित करने में कोई मूल्य नहीं दिखता है जो लक्षित प्लेटफॉर्म या अधिकांश कार्यों को समझने के लिए समझ में आते हैं जो लोग एक कंपाइलर का उपयोग करने के लिए उपयोग करेंगे।
 – 
supercat
22 फरवरी 2020, 09:05
2
@supercat: "सभी मॉडल गलत हैं। कुछ मॉडल उपयोगी होते हैं।" सभी भौतिकी मॉडल गलत हैं - कुछ भी घर्षण रहित नहीं है, कुछ भी न्यूटनियन नहीं है, वास्तविक ठोस में बिल्कुल जड़ता के क्षण नहीं होते हैं जो मॉडल उपयोग करते हैं। मानव शरीर ठीक वैसे ही प्रतिक्रिया नहीं करता है जैसा कि चिकित्सा मॉडल, जैसे कि दवाओं के आधे जीवन की भविष्यवाणी करते हैं। रासायनिक तैयारी अशुद्ध हैं। और कंपाइलर अपूर्ण हैं और सी मानक सीमित है। इससे छुटकारा मिले। सी मानक व्यवहार में बेहद उपयोगी है। यह शुद्ध गणितीय मॉडल नहीं है जिसे आप चाहते हैं। इसके बारे में लगातार चिल्लाना बंद करो।
 – 
Eric Postpischil
22 फरवरी 2020, 14:01

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

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

एक व्यावहारिक दृष्टिकोण से, स्वच्छ रैपराउंड शब्दार्थ की गारंटी देने में पूर्णांक गणनाओं को व्यवहार करने की अनुमति देने की तुलना में थोड़ा अधिक खर्च होता है, जैसे कि अनिर्दिष्ट समय पर बड़े प्रकारों पर प्रदर्शन किया जाता है। यहां तक ​​कि "ऑप्टिमाइज़ेशन" के अभाव में भी, long1 = int1*int2+long2; जैसे एक्सप्रेशन के लिए सीधी कोड जनरेशन भी कई प्लेटफॉर्म पर 16x16->32 या 32x32->64 मल्टीप्लाई इंस्ट्रक्शन के परिणाम का उपयोग करने में सक्षम होने से लाभान्वित होगी, बल्कि परिणाम के निचले आधे हिस्से पर हस्ताक्षर-विस्तार करने की तुलना में। इसके अलावा, एक कंपाइलर को अपनी सुविधानुसार x से बड़े प्रकार के रूप में x+1 का मूल्यांकन करने की अनुमति देने से वह x+1 > y को x >= y से बदल सकता है - आमतौर पर एक उपयोगी और सुरक्षित अनुकूलन।

हालांकि, जीसीसी जैसे कंपाइलर आगे बढ़ते हैं। हालांकि मानक के लेखकों ने देखा कि कुछ इस तरह के मूल्यांकन में:

unsigned mul(unsigned short x, unsigned short y) { return x*y; }

x और y को हस्ताक्षरित int में बढ़ावा देने का मानक का निर्णय unsigned ("दोनों योजनाएं अधिकांश मामलों में एक ही उत्तर, और दोनों दो-पूरक अंकगणित और हस्ताक्षरित अतिप्रवाह पर शांत रैपराउंड के साथ कार्यान्वयन में और भी अधिक मामलों में एक ही प्रभावी परिणाम देते हैं - यानी अधिकांश वर्तमान कार्यान्वयन में।"), जीसीसी कभी-कभी उपयोग करेगा उपरोक्त फ़ंक्शन कॉलिंग कोड के भीतर अनुमान लगाने के लिए है कि x संभवतः INT_MAX/y से अधिक नहीं हो सकता है। मैंने कोई सबूत नहीं देखा है कि मानक के लेखकों ने इस तरह के व्यवहार का अनुमान लगाया था, इसे प्रोत्साहित करने का इरादा तो बिल्कुल भी नहीं था। जबकि जीसीसी के लेखक किसी भी कोड का दावा करते हैं जो ऐसे मामलों में अतिप्रवाह का आह्वान करेगा, "टूटा हुआ" है, मुझे नहीं लगता कि मानक के लेखक सहमत होंगे, क्योंकि अनुरूपता पर चर्चा करते हुए, वे ध्यान देते हैं: "लक्ष्य प्रोग्रामर को देना है a शक्तिशाली सी प्रोग्राम बनाने के लिए लड़ने का मौका जो अत्यधिक पोर्टेबल भी हैं, पूरी तरह से उपयोगी सी प्रोग्रामों को नीचा दिखाने के बिना, जो पोर्टेबल नहीं होते हैं, इस प्रकार क्रिया विशेषण सख्ती से।"

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

-1
supercat 23 जिंदा 2020, 06:34