क्या "वाष्पशील" मल्टी-कोर सिस्टम के लिए पोर्टेबल सी कोड में कुछ भी गारंटी देता है?


12

अन्य प्रश्नों और उनके जवाबों के एक समूह को देखने के बाद , मुझे यह धारणा मिली कि सी में "वाष्पशील" कीवर्ड का व्यापक रूप से कोई समझौता नहीं है।

यहां तक ​​कि मानक अपने आप में सभी के लिए पर्याप्त रूप से स्पष्ट नहीं लगता है कि इसका क्या मतलब है

अन्य समस्याओं में:

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

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

USE 1
वाष्पशील का एकमात्र व्यापक रूप से सहमत-उपयोग पुराने या एम्बेडेड सिस्टम के लिए प्रतीत होता है, जहाँ कुछ मेमोरी लोकेशन I / O फ़ंक्शंस में हार्डवेयर-मैप किए जाते हैं, जैसे मेमोरी में थोड़ा सा नियंत्रण (सीधे, हार्डवेयर में) एक लाइट या स्मृति में एक बिट जो आपको बताता है कि कीबोर्ड कुंजी नीचे है या नहीं (क्योंकि यह हार्डवेयर द्वारा सीधे कुंजी से जुड़ा है)।

ऐसा लगता है कि "उपयोग 1" पोर्टेबल कोड में नहीं होता है जिनके लक्ष्य में मल्टी-कोर सिस्टम शामिल हैं।

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

तो "उपयोग 2" लगता है कि "अस्थिर" क्या दे सकता है।

USE 3
केवल अन्य निर्विवाद उपयोग जो मैं देख रहा हूं, विभिन्न चर के माध्यम से एक्सेस के गलत अनुकूलन को रोकने के लिए एक ही मेमोरी की ओर इशारा करते हैं जो संकलक को एहसास नहीं होता है। लेकिन यह शायद केवल निर्विवाद है क्योंकि लोग इसके बारे में बात नहीं कर रहे हैं - मैंने केवल इसका एक उल्लेख देखा। और मुझे लगा कि सी मानक पहले से ही मान्यता प्राप्त है कि "अलग" पॉइंटर्स (जैसे एक फ़ंक्शन के लिए अलग-अलग args) एक ही आइटम या आस-पास के आइटम को इंगित कर सकते हैं, और पहले से ही निर्दिष्ट है कि कंपाइलर को कोड का उत्पादन करना चाहिए जो ऐसे मामलों में भी काम करता है। हालाँकि, मैं इस विषय को नवीनतम (500 पेज!) मानक में जल्दी नहीं खोज सका।

तो "3 का उपयोग करें" शायद सभी में मौजूद नहीं है ?

इसलिए मेरा सवाल:

क्या "वाष्पशील" मल्टी-कोर सिस्टम के लिए पोर्टेबल सी कोड में कुछ भी गारंटी देता है?


EDIT - अपडेट

नवीनतम मानक ब्राउज़ करने के बाद , ऐसा लग रहा है कि उत्तर कम से कम बहुत सीमित हां है:
1. मानक बार-बार विशिष्ट प्रकार के "वाष्पशील sig_atomic_t" के लिए विशेष उपचार निर्दिष्ट करता है। हालाँकि मानक यह भी कहता है कि एक बहु-थ्रेडेड प्रोग्राम में सिग्नल फ़ंक्शन के उपयोग से अपरिभाषित व्यवहार होता है। इसलिए यह उपयोग मामला एकल-थ्रेडेड प्रोग्राम और इसके सिग्नल हैंडलर के बीच संचार तक सीमित लगता है।
2. मानक भी setjmp / longjmp के संबंध में "अस्थिर" के लिए एक स्पष्ट अर्थ निर्दिष्ट करता है। (उदाहरण कोड जहां यह मायने रखता है अन्य प्रश्नों और उत्तरों में दिया गया है ।)

इसलिए अधिक सटीक प्रश्न बन जाता है:
क्या "वाष्पशील" मल्टी-कोर सिस्टम के लिए पोर्टेबल सी कोड में कुछ भी गारंटी देता है, इसके अलावा (1) एक एकल-थ्रेडेड प्रोग्राम को अपने सिग्नल हैंडलर से जानकारी प्राप्त करने की अनुमति देता है, या (2) सेटजम्प की अनुमति देता है सेजम्प और लॉन्गजम्प के बीच संशोधित चर को देखने के लिए कोड?

यह अभी भी एक हाँ / नहीं सवाल है।

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


3
पोर्टेबल सी में सिग्नल मौजूद हैं; सिग्नल हैंडलर द्वारा अपडेट किए गए वैश्विक चर के बारे में क्या? इस volatileकार्यक्रम को सूचित करने की आवश्यकता होगी कि यह अतुल्यकालिक रूप से बदल सकता है।
नैट एल्ड्रेडगे

2
@NateEldredge Global, जबकि अकेले अस्थिर, पर्याप्त अच्छा नहीं है। इसके साथ ही परमाणु होना भी आवश्यक है।
यूजीन श।

@ यूजीनश: हां, बिल्कुल। लेकिन हाथ पर सवाल volatileविशेष रूप से है, जो मुझे विश्वास है कि आवश्यक है।
नैट एल्ड्रेडगे

" एल 1 कैश के साथ समन्वय करते समय अन्य थ्रेड्स के साथ समन्वय के बारे में कुछ और गारंटी नहीं देता है" डब्ल्यू / अन्य थ्रेड्स को संवाद करने के लिए पर्याप्त नहीं "एल 1 कैश के साथ समन्वय" कहां है?
जिज्ञासु

1
शायद प्रासंगिक, सी ++ प्रस्ताव अस्थिर उतार-चढ़ाव करने के लिए , प्रस्ताव आपके द्वारा उठाए गए कई चिंताओं को संबोधित करता है, और शायद इसका परिणाम सी समिति के लिए प्रभावशाली होगा
एमएम

जवाबों:


1

समस्या को सारांशित करने के लिए, यह प्रकट होता है (बहुत पढ़ने के बाद) कि "वाष्पशील" कुछ गारंटी देता है: मान केवल एक रजिस्टर से / के लिए नहीं बल्कि कम से कम कोर के एल 1 कैश में पढ़ा / लिखा जाएगा , उसी क्रम में कोड में रीड / राइट दिखाई देते हैं

नहीं, यह बिल्कुल नहीं है । और यह एमटी सुरक्षित कोड के उद्देश्य के लिए अस्थिर बनाता है।

यदि ऐसा किया जाता है, तो कई थ्रेड द्वारा साझा किए गए चरों के लिए अस्थिरता काफी अच्छी होगी, क्योंकि L1 कैश में घटनाओं को क्रमबद्ध करने के लिए आपको केवल विशिष्ट सीपीयू (मदरबोर्ड पर मल्टी-कोर या मल्टी-सीपीयू) करने में सक्षम होना चाहिए। एक तरह से जो सी / सी ++ या जावा के सामान्य कार्यान्वयन को विशिष्ट अपेक्षित लागतों के साथ संभव बनाता है (जो कि अधिकांश परमाणु या गैर-सामग्री वाले म्यूटेक्स संचालन पर बहुत बड़ी लागत नहीं है)।

लेकिन अस्थिर या तो सिद्धांत रूप में या व्यवहार में कैश में कोई गारंटीकृत आदेश (या "मेमोरी विजिबिलिटी") प्रदान नहीं करता है ।

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

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

  • आप ptraceअस्थिर वस्तुओं से जुड़े संचालन के बाद अनुक्रम बिंदुओं पर सार्थक विराम बिंदुओं को सेट करने के लिए (एक ptrace जैसी व्यवस्था) का उपयोग कर सकते हैं : आप वास्तव में इन बिंदुओं पर विराम लगा सकते हैं (ध्यान दें कि यह केवल तभी काम करता है जब आप कई विराम बिंदुओं को सेट करने के लिए तैयार हों C / C ++ स्टेटमेंट को कई अलग-अलग असेंबली स्टार्ट और एंड पॉइंट्स में संकलित किया जा सकता है, जैसा कि बड़े पैमाने पर अनियंत्रित लूप में होता है);
  • जबकि रोक के निष्पादन का एक धागा, आप सभी अस्थिर वस्तुओं के मूल्य को पढ़ सकते हैं, क्योंकि उनके पास उनका विहित प्रतिनिधित्व है (एबीआई उनके संबंधित प्रकार के लिए); एक गैर वाष्पशील स्थानीय चर में एक एटिपिकल प्रतिनिधित्व हो सकता है, f.ex. एक स्थानांतरित प्रतिनिधित्व: एक सरणी को अनुक्रमित करने के लिए उपयोग किया जाने वाला चर आसान अनुक्रमण के लिए व्यक्तिगत वस्तुओं के आकार से गुणा किया जा सकता है; या इसे एक सरणी तत्व के लिए एक पॉइंटर द्वारा प्रतिस्थापित किया जा सकता है (जब तक कि चर के सभी उपयोग समान रूप से परिवर्तित हो जाएं) (एक इंटीग्रल में डुक्स को डु में बदलते हुए देखें);
  • आप उन वस्तुओं को भी संशोधित कर सकते हैं (जब तक कि मेमोरी मैपिंग की अनुमति हो, स्थैतिक जीवनकाल के साथ वाष्पशील वस्तु के रूप में जो कास्ट योग्य हैं, केवल एक मेमोरी रेंज में हो सकती है, जिसे मैप किया गया हो)।

अभ्यास में अस्थिर गारंटी, सख्त ptrace की व्याख्या से थोड़ी अधिक है: यह भी गारंटी देता है कि अस्थिर स्वचालित चर का स्टैक पर एक पता है, क्योंकि वे एक रजिस्टर को आवंटित नहीं किए जाते हैं, एक रजिस्टर आवंटन जो ptrace जोड़तोड़ को और अधिक नाजुक बना देगा (संकलक) आउटपुट डिबग जानकारी यह समझाने के लिए कि चर को रजिस्टरों में कैसे आवंटित किया जाता है, लेकिन रजिस्टर राज्य को पढ़ना और बदलना स्मृति पतों तक पहुंचने से थोड़ा अधिक शामिल है)।

ध्यान दें कि पूर्ण कार्यक्रम डिबग-क्षमता, जो कम से कम अनुक्रम बिंदुओं में सभी चर अस्थिरता पर विचार कर रहा है, को संकलक के "शून्य अनुकूलन" मोड द्वारा प्रदान किया जाता है, एक मोड जो अभी भी अंकगणितीय सरलीकरण की तरह तुच्छ अनुकूलन करता है (आमतौर पर कोई गारंटी नहीं है सभी मोड पर अनुकूलन)। लेकिन अस्थिरता गैर-अनुकूलन की तुलना में अधिक मजबूत है: x-xएक गैर-अस्थिर पूर्णांक के लिए सरलीकृत किया जा सकता है, xलेकिन एक अस्थिर वस्तु का नहीं।

इसलिए अस्थिर साधन को संकलित किए जाने की गारंटी दी जाती है , जैसे कि सिस्टम कॉल के कंपाइलर द्वारा स्रोत से बाइनरी / असेंबली में अनुवाद किसी कंपाइलर द्वारा किसी भी तरह से पुनर्व्याख्या, परिवर्तित या अनुकूलित नहीं है। ध्यान दें कि लाइब्रेरी कॉल सिस्टम कॉल हो सकती है या नहीं। कई आधिकारिक सिस्टम फ़ंक्शंस वास्तव में लाइब्रेरी फ़ंक्शन होते हैं जो इंटरपोज़िशन की एक पतली परत की पेशकश करते हैं और आम तौर पर अंत में कर्नेल को सुरक्षित करते हैं। (विशेष रूप getpidसे कर्नेल में जाने की जरूरत नहीं है और अच्छी तरह से जानकारी युक्त ओएस द्वारा प्रदान की गई मेमोरी लोकेशन पढ़ सकता है।)

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

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

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

लेकिन वाष्पशील कोई विशेष स्मृति मामलों को करने के लिए विशेष मामलों के लिए कम से कम अनुकूलित के लिए अपेक्षित असेंबली के उत्सर्जन को मजबूर करने से अधिक नहीं है: वाष्पशील शब्दार्थ का अर्थ है सामान्य मामला अर्थ।

सामान्य मामला वह है जो कंपाइलर तब करता है जब उसे किसी निर्माण के बारे में कोई जानकारी न हो: f.ex. डायनामिक डिस्पैच के माध्यम से एक अंतराल पर एक वर्चुअल फ़ंक्शन को कॉल करना एक सामान्य मामला है, अभिव्यक्ति के द्वारा निर्दिष्ट ऑब्जेक्ट के प्रकार का संकलन समय पर निर्धारित करने के बाद ओवरराइड को सीधे कॉल करना एक विशेष मामला है। कंपाइलर के पास हमेशा सभी निर्माणों का एक सामान्य मामला होता है, और यह ABI का अनुसरण करता है।

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

  • वाष्पशील कुछ भी नहीं कहता है कि कौन से मेमोरी ऑपरेशन मुख्य रैम तक पहुंचते हैं (आप इन गारंटी प्राप्त करने के लिए विधानसभा निर्देशों या सिस्टम कॉल के साथ विशिष्ट मेमोरी कैशिंग प्रकार सेट कर सकते हैं);
  • जब मेमोरी ऑपरेशन कैश के किसी भी स्तर (एल 1 भी नहीं) के लिए प्रतिबद्ध होंगे, तो अस्थिरता कोई गारंटी नहीं देती है

केवल दूसरी बात का मतलब है कि अधिकांश अंतर सूत्र संचार समस्याओं में अस्थिरता उपयोगी नहीं है; पहला बिंदु अनिवार्य रूप से किसी भी प्रोग्रामिंग समस्या में अप्रासंगिक है जिसमें सीपीयू (एस) के बाहर हार्डवेयर घटकों के साथ संचार शामिल नहीं है लेकिन फिर भी मेमोरी बस पर।

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

जब तक आप अपने थ्रेड्स को सिग्नल भेजने की योजना नहीं बनाते हैं (वर्तमान में बिना किसी रोक-टोक के सहमति से चलने वाले थ्रेड्स के बारे में जानकारी के समेकन के लिए एक अत्यंत उपयोगी दृष्टिकोण), अस्थिर आपके लिए नहीं है।


6

मैं कोई विशेषज्ञ नहीं हूं, लेकिन cppreference.com ने मुझे कुछ अच्छी अच्छी जानकारी दी हैvolatile । यहाँ इसका सार है:

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

यह कुछ उपयोग भी देता है:

वाष्पशील का उपयोग

1) स्थैतिक वाष्पशील वस्तुएं मॉडल मेमोरी-मैप्ड I / O पोर्ट्स, और स्टैटिक कॉन्स्टेबल वोलेटाइल ऑब्जेक्ट्स मेमोरी-मैप्ड इनपुट पोर्ट्स, जैसे कि एक वास्तविक समय घड़ी

2) प्रकार sig_atomic_t के स्थिर अस्थिर वस्तुओं का उपयोग सिग्नल हैंडलर के साथ संचार के लिए किया जाता है।

3) अस्थिर चर जो किसी फ़ंक्शन के लिए स्थानीय होते हैं जिसमें सेटजंप मैक्रो का एक आह्वान होता है, केवल लॉन्गजेम्प रिटर्न के बाद अपने मूल्यों को बनाए रखने के लिए गारंटी वाले स्थानीय चर होते हैं।

4) इसके अलावा, अस्थिर चर का उपयोग अनुकूलन के कुछ रूपों को निष्क्रिय करने के लिए किया जा सकता है, उदाहरण के लिए मृत स्टोर उन्मूलन या माइक्रोबेनचर्च के लिए निरंतर तह।

और हां, यह उल्लेख करता है कि volatileथ्रेड सिंक्रोनाइज़ेशन के लिए उपयोगी नहीं है:

ध्यान दें कि थ्रेड के बीच संचार के लिए अस्थिर चर उपयुक्त नहीं हैं; वे परमाणु, तुल्यकालन, या मेमोरी ऑर्डर करने की पेशकश नहीं करते हैं। एक अस्थिर चर से पढ़ा गया है जो बिना किसी सिंक्रनाइज़ेशन या दो असंबद्ध थ्रेड से समवर्ती संशोधन द्वारा संशोधित किया गया है डेटा दौड़ के कारण अपरिभाषित व्यवहार है।


2
विशेष रूप से, (2) और (3) पोर्टेबल कोड के लिए प्रासंगिक हैं।
नैट एल्ड्रेडेज 14

2
@TED ​​डोमेन नाम के बावजूद, लिंक C के बारे में है, C ++ के बारे में नहीं
डेविड ब्राउन

@NateEldredge आप longjmpC ++ कोड में शायद ही कभी उपयोग कर सकते हैं ।
जिज्ञासु

@DavidBrown C और C ++ में एक देखने योग्य SE की समान परिभाषा है, और अनिवार्य रूप से एक ही थ्रेड प्राइमेटिव हैं।
जिज्ञासु

4

सबसे पहले, ऐतिहासिक रूप से volatileपहुंच और समान के अर्थ के विभिन्न अंतर्ज्ञान के बारे में विभिन्न हिचकी हैं । इस अध्ययन को देखें: Volatiles Are Miscompiled, और क्या करना है इसके बारे में

उस अध्ययन में उल्लिखित विभिन्न मुद्दों के अलावा, का व्यवहार volatileपोर्टेबल है, उनमें से एक पहलू के लिए बचाएं: जब वे स्मृति बाधाओं के रूप में कार्य करते हैं । एक मेमोरी बैरियर कुछ तंत्र है जो आपके कोड के समवर्ती अप्रकाशित निष्पादन को रोकने के लिए है। volatileमेमोरी बैरियर के रूप में उपयोग करना निश्चित रूप से पोर्टेबल नहीं है।

सी भाषा स्मृति व्यवहार की गारंटी देती है या नहीं volatileयह स्पष्ट रूप से तर्कपूर्ण है, हालांकि व्यक्तिगत रूप से मुझे लगता है कि भाषा स्पष्ट है। पहले हमारे पास साइड इफेक्ट्स की औपचारिक परिभाषा है, C17 5.1.2.3:

किसी volatileऑब्जेक्ट तक पहुँचना, किसी ऑब्जेक्ट को संशोधित करना, किसी फ़ाइल को संशोधित करना, या किसी ऐसे फ़ंक्शन को कॉल करना जो उन सभी कार्यों में से कोई भी हो, सभी साइड इफेक्ट होते हैं , जो निष्पादन वातावरण की स्थिति में परिवर्तन होते हैं।

मानक मूल्यांकन (निष्पादन) के क्रम को निर्धारित करने के तरीके के रूप में शब्द अनुक्रमण को परिभाषित करता है। परिभाषा औपचारिक और बोझिल है:

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

उपरोक्त के टीआर; डीआर मूल रूप से यह है कि यदि हमारे पास एक अभिव्यक्ति है Aजिसमें साइड-इफेक्ट होते हैं, तो इसे दूसरे एक्सप्रेशन से पहले निष्पादित किया जाना चाहिए B, यदि Bबाद में अनुक्रम किया जाता है A

इस भाग के माध्यम से C कोड का अनुकूलन संभव है:

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

इसका मतलब यह है कि कार्यक्रम उस क्रम में मूल्यांकन (निष्पादित) कर सकता है जो मानक कहीं और करता है (मूल्यांकन आदि का क्रम)। लेकिन इसका मूल्यांकन करने (निष्पादित करने) की आवश्यकता नहीं है यदि यह कटौती कर सकता है कि इसका उपयोग नहीं किया गया है। उदाहरण के लिए, ऑपरेशन 0 * xको मूल्यांकन करने की आवश्यकता नहीं है xऔर बस अभिव्यक्ति को प्रतिस्थापित करना है 0

जब तक किसी वैरिएबल तक पहुंचना साइड-इफेक्ट नहीं है। मतलब यह है कि यदि इसका परिणाम मूल्यांकन (निष्पादित) करनाx है volatile, तो भी परिणाम हमेशा 0. होगा। अनुकूलन की अनुमति नहीं है।0 * x

इसके अलावा, मानक अवलोकनीय व्यवहार की बात करते हैं:

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

  • अमूर्त मशीन के नियमों के अनुसार अस्थिर वस्तुओं तक पहुंच का कड़ाई से मूल्यांकन किया जाता है।
    / - / यह कार्यक्रम का अवलोकनीय व्यवहार है।

उपरोक्त सभी को देखते हुए, एक अनुरूप कार्यान्वयन (संकलक + अंतर्निहित प्रणाली) volatileएक अनपेक्षित क्रम में वस्तुओं की पहुंच को निष्पादित नहीं कर सकता है , अगर लिखित सी स्रोत के शब्दार्थ अन्यथा कहते हैं।

इसका मतलब है कि इस उदाहरण में

volatile int x;
volatile int y;
z = x;
z = y;

दोनों काम भाव चाहिए मूल्यांकन किया जाना और z = x; चाहिए से पहले मूल्यांकन किया जाना z = y;। एक बहु-प्रोसेसर कार्यान्वयन जो इन दो ऑपरेशनों को दो अलग-अलग अनियंत्रित कोर को आउटसोर्स करता है, अनुरूप नहीं है!

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

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


@curiousguy कोई फर्क नहीं पड़ता।
लुंडिन

@curiousguy कोई फर्क नहीं पड़ता, जब तक कि यह क्वालीफायर के साथ या बिना पूर्णांक प्रकार के कुछ प्रकार है।
लुंडिन

यदि यह एक साधारण गैर वाष्पशील पूर्णांक है, तो निरर्थक zवास्तव में निष्पादित क्यों होता है ? (जैसे z = x; z = y;) अगले बयान में मूल्य को मिटा दिया जाएगा।
जिज्ञासु

@curiousguy क्योंकि पढ़ता अस्थिर चर करने के लिए निर्दिष्ट क्रम में, कोई फर्क नहीं पड़ता निष्पादित किया जाना है।
लुंडिन

फिर zवास्तव में दो बार सौंपा गया है? आप कैसे जानते हैं कि "रीड्स निष्पादित होते हैं"?
क्यूरियस गुयेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.