2010-02-01 11 views
10

यानी, क्या निम्न बहुमत वाले वातावरण में भी सही ढंग से निष्पादित होने की उम्मीद की जाएगी?सी ++ में, आदिम प्रकारों के स्थैतिक प्रारंभिक स्थिर मान थ्रेड-सुरक्षित हैं?

int dostuff(void) { 
    static int somevalue = 12345; 
    return somevalue; 
} 

या यह एक से अधिक थ्रेड यह कॉल करने के लिए संभव है, और एक कॉल वापस जाने के लिए जो कुछ भी कचरा &somevalue पर था से पहले निष्पादन के लिए शुरू किया?

+0

स्थिर स्थिरांक एक विकल्प नहीं है पर निर्भर करने लगता है? –

+0

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

+1

तकनीकी रूप से नहीं। लेकिन जीसीसी के पास यह स्पष्ट करने के लिए एक स्पष्ट पैच है कि यह एक बहुप्रचारित वातावरण में काम करता है। –

उत्तर

2

सी ++ स्टैंडर्ड से, खंड 6.7:

से पहले अपने ब्लॉक पहले दर्ज किया गया है स्थिर भंडारण अवधि निरंतर-भाव साथ प्रारंभ साथ पॉड प्रकार (3.9) के एक स्थानीय वस्तु आरंभ नहीं हो जाता।

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

+0

एघ, मानक में यह नहीं मिला। फिर से आह! वही खंड कहता है: "स्थिर भंडारण अवधि (3.7.1) के साथ सभी स्थानीय वस्तुओं का शून्य-प्रारंभिक (8.5) किसी अन्य प्रारंभिक होने से पहले किया जाता है।" तो, यदि प्रारंभिक मान 0 है, तो 0 का मान (मानकों के अनुसार) एक बहुप्रचारित वातावरण में भी वैध होना चाहिए, हां? –

+0

यह निश्चित रूप से ऐसा लगता है। –

+0

बस यह सुनिश्चित कर लें कि मैंने इसे सही तरीके से पढ़ा है। धन्यवाद। :) –

4

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

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

push rbp 
mov rbp,rsp 
lea rax,[rip+0x2067]  # 0x100003170 <_ZZ7dostuffvE9somevalue> 
mov eax,DWORD PTR [rax] 
leave 
ret

आप देख सकते हैं, वहाँ कोई काम है:

ओएस एक्स 10.6.2 के लिए जी ++ पर, इस मशीन अपने समारोह के लिए तैयार किए गए कोड है। कंपाइलर ने निर्माण समय पर आदिम को पकाया है।

+0

एएसएम के लिए +1, हालांकि यह कंपाइलर विशिष्ट है :-) – Justicle

+0

इसके अलावा, अगर एएसएम वास्तव में फ़ंक्शन के भीतर संशोधित किया गया था तो मुझे एएसएम देखना होगा - मुझे लगता है कि जीसीसी ने यहां कुछ अनुकूलन किया है। मुझे लगता है कि परिणामस्वरूप कोड अधिक होगा: http://stackoverflow.com/questions/2180501/in-c-are-static-initializations-of-primitive-types-to-constant-values-thread-s/ 2180547 # 2180547 – Justicle

+0

जब मैं मूल्य बढ़ाता हूं, तो यह वृद्धि एएसएम को छोड़कर बिल्कुल ऊपर जैसा दिखता है। मूल्य को म्यूट करना एक दौड़ पेश करता है, लेकिन शुरुआत के कारण नहीं, जो अभी भी अनुपस्थित है। – pestilence669

2

क्योंकि कुछ शुरुआती प्रारंभकर्ता को कन्स्ट्रक्टर कॉल की आवश्यकता नहीं होती है, यह ठीक काम करेगा (कुछ समय बिल्ड समय पर शुरू किया जाएगा)।

अब, अगर आप एक मूल्य है कि एक निर्माता के लिए आवश्यक आरंभ गया:

void whatever() 
{ 
    static std::string value("bad"); 

    ... 
} 

तो फिर तुम एक से अधिक थ्रेड के साथ मुसीबत में मिल सकता है। आंतरिक रूप से, कुछ इस तरह में बदल गया हो जाएगी:

void whatever() 
{ 
    static bool value_initialized = false; 
    static string_struct value; 

    if (!initialized) 
    { 
     construct_string(&value, "bad"); 
     value_initialized = false; 
    } 

    .... 
} 

से अधिक थ्रेड की उपस्थिति में, आप दौड़ की स्थिति और स्मृति दृश्यता) सहित विभिन्न समस्याएं हैं।

10

मानक की धारा 6.7 यह कहना है:

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

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

मुझे पता है कि एक गैर-पीओडी ऑब्जेक्ट शुरू करते समय, जीसीसी दो बार शुरू होने से रोकने के लिए एक म्यूटेक्स पकड़ लेता है (मुझे यह पता है क्योंकि मैंने एक बार एक स्थिर वस्तु को शुरू करने के लिए गलती से एक प्रोग्राम को डेडलॉक किया था)।

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

+0

मानक – Justicle

+3

उद्धरण के लिए +1 जीसीसी ने 4.x लाइन में धागे सुरक्षित स्थिरताएं पेश कीं। –

+1

"स्थाई भंडारण अवधि के साथ पीओडी प्रकार का एक स्थानीय ऑब्जेक्ट निरंतर अभिव्यक्तियों के साथ आरंभ किया गया है, इससे पहले कि इसका ब्लॉक पहले दर्ज किया गया हो।" यानी स्टार्टअप पर नहीं। –

0
मेरे अनुभव स्थिर फ़ाइल दायरे में परिभाषित के व्यवहार से

एक स्थिर एक समारोह

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

ध्यान दें कि यह संकलक संस्करणों (जो आप को देखते हुए उम्मीद करेंगे कि हम 'अपरिभाषित' व्यवहार क्षेत्रों में चल रहे हैं)

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