2010-06-14 7 views
17

मैं एक किताब से SIOF के बारे में पढ़ रहा था और यह एक उदाहरण दिया:स्थिर आरंभीकरण आदेश असफलता

//file1.cpp 
extern int y; 
int x=y+1; 

//file2.cpp 
extern int x; 
int y=x+1; 

अब मेरे सवाल यह है:
उपरोक्त कोड में, निम्नलिखित बातें क्या होगा?

  1. फ़ाइल 1.cpp संकलित करते समय, कंपाइलर y को छोड़ देता है क्योंकि मैं इसके लिए भंडारण आवंटित नहीं करता हूं।
  2. कंपाइलर एक्स के लिए भंडारण आवंटित करता है, लेकिन इसे प्रारंभ नहीं करता है।
  3. फ़ाइल 2.cpp संकलित करते समय, कंपाइलर x को छोड़ देता है क्योंकि मैं इसके लिए भंडारण आवंटित नहीं करता हूं।
  4. कंपाइलर वाई के लिए भंडारण आवंटित करता है, लेकिन इसे प्रारंभ नहीं करता है।
  5. file1.o और file2.o को लिंक करते समय, अब file2.o को पहले प्रारंभ किया जाना चाहिए, इसलिए अब:
    क्या x को प्रारंभिक मान 0 मिलता है? या शुरू नहीं किया गया है?

उत्तर

10

प्रारंभ चरणों 3.6.2 सी ++ मानक के "गैर स्थानीय वस्तुओं का प्रारंभ" में दिए गए हैं:

चरण 1: x और y शून्य प्रारंभ से पहले किसी अन्य प्रारंभ हो जाता है कर रहे हैं।

चरण 2: x या y गतिशील रूप से प्रारंभ किया गया है - जिसे मानक द्वारा निर्दिष्ट नहीं किया गया है।उस चर को मूल्य 1 मिलेगा क्योंकि अन्य चर शून्य-प्रारंभिक होगा।

चरण 3: अन्य चर गतिशील रूप से प्रारंभ किया जाएगा, मूल्य 2 प्राप्त हो रहा है।

+0

धन्यवाद..लेकिन चरण 1 में, जब wll x और y शून्य हो जाएगा: संकलन समय पर या लिंक समय पर? –

+6

@ हैपी मित्तल: आप नहीं बता सकते हैं और इस प्रकार संकलक चुन सकते हैं। यह प्रोग्राम लोड समय पर भी हो सकता है। – MSalters

1

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

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

मुझे लगता है कि सबसे अधिक संभावना परिदृश्य होगा:

  1. अंतरिक्ष चर के लिए आवंटित किया जाता है, और दोनों मूल्य 0.
  2. एक चर है, का कहना है कि एक्स, प्रारंभ और मूल्य 1 पर सेट है ।
  3. अन्य का कहना है कि y, प्रारंभ और मूल्य 2.

तुम हमेशा इसे चलाने सकता है और देखने के लिए निर्धारित है। यह हो सकता है कि कुछ कंपाइलर कोड उत्पन्न करेंगे जो एक अनंत लूप में जाता है।

+0

लेकिन मेरा संदेह यह है कि यदि कंपाइलर बाहरी int y के लिए भंडारण आवंटित नहीं करता है, तो यह इसे शून्य पर कैसे प्रारंभ कर सकता है? या जब y शून्य पर प्रारंभ किया गया है? संकलन समय या लिंक समय पर? क्या कोई नियम है जो प्रारंभ होने पर परिवर्तनीय हो जाता है? –

+0

क्या आप चरणबद्ध तरीके से व्याख्या कर सकते हैं कि संकलन और लिंक समय पर क्या होगा/क्या हो सकता है? –

2

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

10

एसआईओफ़ बहुत रनटाइम आर्टिफैक्ट है, संकलक और लिंकर के पास इसके साथ बहुत कुछ नहीं है। Atexit() फ़ंक्शन पर विचार करें, यह कार्यक्रम से बाहर निकलने के लिए फ़ंक्शन पंजीकृत करता है। कई सीआरटी कार्यान्वयन के कार्यक्रम प्रारंभिकरण के लिए कुछ समान है, चलिए इसे atinit() कहते हैं।

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

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

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

संबंधित मुद्दे