कंपाइलर को एक स्थानीय अस्थिर को निरंतर-गुना करने की अनुमति है?


25

इस सरल कोड पर विचार करें:

void g();

void foo()
{
    volatile bool x = false;
    if (x)
        g();
}

https://godbolt.org/z/I2kBY7

आप संभावित कॉल को न तो देख सकते हैं gccऔर न ही clangऑप्टिमाइज़ कर सकते हैं g। यह मेरी समझ में सही है: अमूर्त मशीन यह मानने के लिए है कि volatileचर किसी भी क्षण (उदाहरण के लिए हार्डवेयर-मैप किए जाने के कारण) बदल सकते हैं, इसलिए चेक falseमें इनिशियलाइज़ेशन को लगातार मोड़ना ifगलत होगा।

लेकिन MSVC कॉल को gपूरी तरह से समाप्त कर देता है ( volatileहालांकि पढ़ता है और हालांकि लिखता है !)। क्या यह मानक-अनुरूप व्यवहार है?


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


संपादन:

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

  • मैं xइस मुद्दे को साइड-स्टेप करने के लिए एक गैर-स्थानीय चर बना सकता हूं । यह प्रश्न जिज्ञासा से अधिक है।


3
यह मेरे लिए एक स्पष्ट संकलक बग जैसा दिखता है।
सैम वार्शविक

1
जहां तक ​​मुझे पता है कि यह नियम के तहत कानूनी है। संकलक यह साबित कर सकता है कि भले ही वस्तु अस्थिर है, फिर भी इसे संशोधित करने की स्थिति के लिए कोई रास्ता नहीं है, इसलिए इसे तह किया जा सकता है। मुझे विश्वास नहीं है कि एक उत्तर में डाल दूं, लेकिन मुझे लगता है कि यह सही है।
नाथनऑलिवर

3
लेकिन मुझे लगता है कि ओपी का तर्क है कि चर को डिबगर द्वारा संशोधित किया जा सकता है। शायद किसी को MSVC के साथ बग रिपोर्ट दर्ज करनी चाहिए।
ब्रायन

2
@curiousguy भले ही आप परिणाम को त्याग दें और / या सटीक मान लें, फिर भी आपने इसे पढ़ा है।
Deduplicator

2
दिलचस्प यह है कि यह केवल x64 के लिए है। X86 संस्करण अभी भी g को कॉल करता है () Godbolt.org/z/nc3Y-f
Jerry Jeremiah

जवाबों:


2

मुझे लगता है कि [intro.execution] (पैराग्राफ संख्या भिन्न) MSVC व्यवहार को समझाने के लिए इस्तेमाल किया जा सकता है:

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

मानक वाष्पशील चमक के माध्यम से एक पढ़ने के उन्मूलन की अनुमति नहीं देता है, लेकिन ऊपर के पैराग्राफ को मूल्य की भविष्यवाणी करने की अनुमति के रूप में व्याख्या की जा सकती है false


BTW, C मानक (N1570 6.2.4 / 2) का कहना है कि

एक वस्तु मौजूद है, एक निरंतर पता है, और अपने पूरे जीवनकाल में अपने अंतिम संचित मूल्य को बरकरार रखता है। 34


34) एक अस्थिर वस्तु के मामले में, अंतिम स्टोर को कार्यक्रम में स्पष्ट होने की आवश्यकता नहीं है।

यह स्पष्ट नहीं है कि सी मेमोरी / ऑब्जेक्ट मॉडल में स्वत: भंडारण अवधि के साथ एक गैर-स्पष्ट स्टोर हो सकता है या नहीं।


सहमत हैं कि संकलक को पता चल सकता है कि लक्ष्य मंच पर गैर-स्पष्ट स्टोर कब संभव हैं
एमएम

1
तो अगर यह सच है, तो स्थानीय अस्थिर वस्तुएं (कम से कम MSVC पर) पूरी तरह से व्यर्थ हैं? क्या ऐसा कुछ है जो आपको जोड़ता volatileहै (यदि सुपरफ़्लड रीड्स / राइट्स के अलावा) आपको अनुकूलन उद्देश्यों के लिए अनदेखा किया जाता है?
मैक्स लैंगहॉफ़

1
@MaxLanghof पूरी तरह से व्यर्थ और आप चाहते हैं / उम्मीद काफी प्रभाव नहीं होने के बीच एक अंतर है।
Deduplicator

1
@MaxLanghof फ़्लोटिंग पॉइंट गणनाओं के मध्यवर्ती परिणाम कभी-कभी सटीक मुद्दों के कारण 80-बिट रजिस्टर में पदोन्नत हो जाते हैं। मेरा मानना ​​है कि यह एक gcc-ism है और इस तरह के सभी युगल को अस्थिर घोषित करने से बचा जाता है। देखें: gcc.gnu.org/bugzilla/show_bug.cgi?id=323
फॉरएवर लर्निंग

1
@philipxy PS मेरा उत्तर देखें मुझे पता है कि पहुंच कार्यान्वयन-परिभाषित है। प्रश्न एक्सेस (ऑब्जेक्ट एक्सेस किया गया) के बारे में नहीं है, बल्कि मूल्य की भविष्यवाणी है।
भाषा वकील

2

TL; DR कंपाइलर प्रत्येक वाष्पशील पहुंच पर जो चाहे कर सकता है। लेकिन प्रलेखन को आपको बताना होगा ।-- "एक अस्थिर चमक के माध्यम से पहुंच के शब्दार्थ कार्यान्वयन-परिभाषित हैं।"


एक कार्यक्रम के लिए मानक परिभाषित "अस्थिर पहुंच" और अन्य "अवलोकनीय व्यवहार" ("साइड-इफेक्ट्स" के माध्यम से प्राप्त) के अनुक्रमों को अनुमति देता है कि एक कार्यान्वयन को "जैसा-यदि 'नियम" प्रति सम्मान करना चाहिए।

लेकिन मानक कहता है (मेरा बोल्डफेस जोर):

वर्किंग ड्राफ्ट, प्रोग्रामिंग लैंग्वेज के लिए मानक C ++
डॉक्यूमेंट नंबर: N4659
दिनांक: 2017-03-21

The 10.1.7.1 सीवी-क्वालीफायर

5 एक अस्थिर चमक के माध्यम से एक पहुंच के शब्दार्थ कार्यान्वयन-परिभाषित हैं। [...]

इसी तरह इंटरेक्टिव उपकरणों के लिए (मेरा बोल्डफेस जोर):

Execution 4.6 कार्यक्रम निष्पादन

5 एक सुव्यवस्थित कार्यक्रम को क्रियान्वित करने वाला एक अनुरूप कार्यान्वयन एक ही कार्यक्रम और एक ही इनपुट के साथ अमूर्त मशीन के संगत उदाहरण के संभावित निष्पादन में से एक के रूप में एक ही अवलोकन व्यवहार का उत्पादन करेगा। [...]

7 एक अनुरूप कार्यान्वयन पर कम से कम आवश्यकताएं हैं:

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

इन्हें सामूहिक रूप से कार्यक्रम के अवलोकन योग्य व्यवहार के रूप में जाना जाता है । [...]

(वैसे भी किसी प्रोग्राम के लिए विशिष्ट कोड क्या है यह मानक द्वारा निर्दिष्ट नहीं है।)

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

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

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


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

हां, कार्यान्वयन की गुणवत्ता प्रासंगिक है। फिर भी, फ़ाइलों को लिखने के अलावा, "वेधशाला" [sic] कार्यान्वयन-परिभाषित हैं। यदि आप ब्रेकपॉइंट सेट करने में सक्षम होना चाहते हैं, तो कुछ वास्तविक मेमोरी एक्सेस करें, 'वाष्पशील' को अनदेखा करें, आदि पर अमूर्त वाष्पशील रीड और लिखते हैं, फिर आपको अपने संकलक लेखक को उपयुक्त कोड आउटपुट प्राप्त करना होगा । PS इन C ++ "साइड-इफ़ेक्ट" का उपयोग प्रति सेक्शन ऑब्जर्बके व्यवहार के लिए नहीं किया जाता है, इसका उपयोग सबएक्सप्रेस के आंशिक ऑर्डर मूल्यांकन का वर्णन करने के लिए किया जाता है।
फिलीपिक्सी

[एसआईसी] को समझाने के लिए देखभाल? आप किस स्रोत को उद्धृत कर रहे हैं और क्या गलती है?
मैक्स लैंगहॉफ़

Re sic मेरा सिर्फ इतना मतलब है कि एक सारगर्भित मशीन केवल वास्तविक दुनिया के लिए ही देखने योग्य है अगर कार्यान्वयन यह कहता है कि कैसे और क्या है।
फिलीपिक्सी

1
क्या आप कह रहे हैं कि एक कार्यान्वयन दावा कर सकता है कि एक इंटरैक्टिव डिवाइस जैसी कोई चीज नहीं है, इसलिए कोई भी कार्यक्रम कुछ भी कर सकता है, और यह अभी भी सही होगा? (नोट: मैं इंटरैक्टिव उपकरणों पर आपके जोर को नहीं समझता हूं।)
जिज्ञासु

-1

मेरा मानना ​​है कि चेक को छोड़ना कानूनी है।

वह पैराग्राफ जिसे हर कोई उद्धृत करना पसंद करता है

34) एक अस्थिर वस्तु के मामले में, अंतिम स्टोर को कार्यक्रम में स्पष्ट होने की आवश्यकता नहीं है

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

ऐसा कहने के बाद, मुझे लगता है कि MSVC व्यवहार एक बग है। कॉल को ऑप्टिमाइज़ करने का कोई वास्तविक कारण नहीं है। ऐसा अनुकूलन अनुपालन हो सकता है, लेकिन यह अनावश्यक रूप से बुराई है।


क्या आप समझा सकते हैं कि यह बुराई क्यों है? कोड शो में, फ़ंक्शन को शाब्दिक रूप से कभी नहीं बुलाया जा सकता है।
डेविड श्वार्ट्ज

@DavidSchwartz आप केवल यह निष्कर्ष निकाल सकते हैं कि स्थानीय वाष्पशील चरों के शब्दार्थ को निर्दिष्ट करने के बाद (ऊपर उद्धृत पैराग्राफ देखें)। मानक खुद लिखते हैं कि volatileमाना जाता है कि कार्यान्वयन कि मूल्य कार्यान्वयन के लिए साधन अज्ञात द्वारा बदल सकते हैं करने के लिए एक संकेत हो सकता है।
मैक्स लैंगहॉफ़

@MaxLanghof कार्यान्वयन को सही तरीके से अज्ञात रूप से संभालने के लिए कोई रास्ता नहीं है। वास्तव में जो उपयोगी प्लेटफ़ॉर्म करता है वह निर्दिष्ट करता है कि आप volatileउस प्लेटफ़ॉर्म पर और उस विनिर्देश के बाहर क्या उपयोग कर सकते हैं और नहीं कर सकते , यह हमेशा एक बकवास शूट होने वाला है।
डेविड श्वार्ट्ज

@DavidSchwartz यह निश्चित रूप से - सार मशीन के शब्दार्थ (विशेष रूप से, पढ़ता और लिखता है) का पालन करके कर सकता है। यह सही ढंग से अनुकूलन करने में सक्षम नहीं हो सकता है - यह मानक का बिंदु है। अब, यह एक नोट है और इस तरह यह आदर्श नहीं है, और जैसा कि हम दोनों ने कहा, कार्यान्वयन यह निर्दिष्ट कर सकता है कि क्या volatileकरता है और उस पर टिके रहना चाहिए। मेरा कहना है कि कोड ही (C ++ मानक / अमूर्त मशीन के अनुसार) आपको यह निर्धारित करने की अनुमति नहीं देता है कि क्या gकहा जा सकता है।
मैक्स लैंगहॉफ़

@DavidSchwartz कोड में ऐसा कुछ नहीं दिखाया गया है, क्योंकि निहितार्थ के अभाव में कोड का पालन नहीं होता है।
एन। 'सर्वनाम' मी।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.