2012-03-17 12 views
6

के क्रम को नियंत्रित करना मैं सी ++ 11 के साथ एक छोटा कर्नेल लिख रहा हूं और उसी प्रकार के दो उदाहरण हैं जिन्हें किसी भी अन्य स्थिर वस्तुओं के निर्माण से पहले बनाया जाना है।स्थैतिक वस्तुओं के कन्स्ट्रक्टर

// test.hpp 
class test { 
    // blahblah... 
}; 

// test.cpp 
typedef char fake_inst[sizeof(test)] __attribute__((aligned(alignof(test)))); 

fake_inst inst1; 
fake_inst inst2; 

// main.cpp 
extern test inst1; 
extern test inst2; 

int kmain() { 
    // copy data section 

    // initialize bss section 

    new (&inst1) test(); 
    new (&inst2) test(); 

    // call constructors in .init_array 

    // kernel stuffs 
} 

यह बनाता है और अपेक्षा के अनुरूप नहीं चेतावनी संदेश के बिना, लेकिन LTO साथ नहीं काम करता है:

कोड मैंने लिखा इस प्रकार है।

मुझे मिलान मिलान की शिकायत करने वाले कई चेतावनी संदेश मिलते हैं और मुझे आश्चर्य है कि कोई कामकाज है क्योंकि यह मुझे अन्य 'असली' चेतावनी या त्रुटि संदेशों को खोजने में भ्रमित करता है।

कोई सुझाव?

+0

आप वास्तव में क्या करने की कोशिश कर रहे हैं? नीचे पब्बी के उत्तर की टिप्पणियों में आप कहते हैं कि आप एक ही प्रकार की कई वस्तुओं को प्रारंभ करना चाहते हैं। मेरे लिए, ऐसा लगता है कि कार्यान्वयन को अन्य रचनाकारों को कॉल करने से पहले, आप ढेर जैसे सी ++ समर्थन से संबंधित संरचनाओं को प्रारंभ करना चाहते हैं। लेकिन यह आपके जैसा प्रयास करने की तरह नहीं लगता है। इसके अलावा, आपको किस तरह के "प्रकार मिलान" के बारे में चेतावनियां मिलती हैं? – Potatoswatter

+0

@Potatoswatter बहुत सी चेतावनी: 'xxx' का प्रकार मूल घोषणा [डिफ़ॉल्ट रूप से सक्षम] से मेल नहीं खाता है 'चीजें। ऐसा इसलिए है क्योंकि वास्तविक प्रकार परीक्षण नहीं है लेकिन char []। मैंने सोचा कि मैं स्थैतिक कन्स्ट्रक्टर को अक्षम कर सकता हूं लेकिन ऐसा लगता है कि ऐसा करने का कोई तरीका नहीं है। – kukyakya

+0

आह, मैं देखता हूं। आपको क्या करना चाहिए 'char fake_inst1 [sizeof (test)]; परीक्षण * const inst1 = reinterpet_cast < test * > (fake_inst1); ' – Potatoswatter

उत्तर

0

शायद यह पसंद है?

// ... .h 
template<typename T> 
union FakeUnion { 
    FakeUnion() {} 
    ~FakeUnion() {} 

    T inst; 
}; 

extern FakeUnion<test> inst1_; 
extern FakeUnion<test> inst2_; 
static constexpr test& inst1 = inst1_.inst; 
static constexpr test& inst2 = inst2_.inst; 
// ... .h end 

// ... .cpp 
FakeUnion<test> inst1_; 
FakeUnion<test> inst2_; 
// ... .cpp end 

main के भीतर, आप तो new (&inst1) test; कह सकते हैं। इसे अब असंगतता उल्लंघन के प्रकार के बारे में चेतावनियां नहीं देनी चाहिए, क्योंकि आपके कोड के विपरीत, इस कोड में वेरिएबल्स नहीं हैं जिनमें विभिन्न प्रकार के विभिन्न प्रकार हैं।

+0

हालांकि यह नाम संघर्ष को हल करता है, यह सुनिश्चित नहीं करता है कि 'inst1' और' inst2' के निर्माता को किसी अन्य के सामने बुलाया जाता है। –

+0

@ मैट अगर वह उन्हें प्लेसमेंट के साथ 'मुख्य' में बुलाता है, तो यह सुनिश्चित करता है कि यदि अन्य सभी सीटीओ को नियंत्रित तरीके से 'मुख्य' के बाद बुलाया जाता है। –

+0

क्या आप यहां सलाह दे सकते हैं कि "जादू" क्या हो रहा है? अर्थात। हमें एक संघ की आवश्यकता क्यों है और संघ के पास ctor/dtor क्यों है? – Farcaller

1

क्या आप जीसीसी की init_priority विशेषता का उपयोग कर सकते हैं?

Some_Class A __attribute__ ((init_priority (2000))); 
Some_Class B __attribute__ ((init_priority (543))); 

http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#C_002b_002b-Attributes

+0

मैंने इसके बारे में पढ़ा है लेकिन रचनाकारों के आदेश को प्रबंधित करना मुश्किल है क्योंकि प्राथमिकताएं स्रोत फ़ाइलों पर फैली हुई हैं। – kukyakya

+0

@ कुकायाक्य तो मुद्दा पहले दो वस्तुओं को शुरू कर रहा है, या सामान्य रूप से सभी वैश्विक रचनाकारों को आदेश दे रहा है? – Potatoswatter

+0

@Potatoswatter वास्तव में यह केवल दो उदाहरणों के बारे में नहीं है, लेकिन एक ही प्रकार के लिए एक से अधिक उदाहरण हैं, इसलिए मैं सिंगलटन पैटर्न का उपयोग नहीं कर सकता। अन्य स्थैतिक वस्तुओं का निर्माण आदेश कोई फर्क नहीं पड़ता। – kukyakya

0
// in an .h file 

typedef char fake_inst[sizeof(test)] __attribute__((aligned(__alignof__(test)))); 

extern fake_inst fake_inst1; 
extern fake_inst fake_inst2; 

inline test& f_inst1() { return *reinterpret_cast<test*>(fake_inst1); } 
inline test& f_inst2() { return *reinterpret_cast<test*>(fake_inst2); } 

// and for readability 

static test& inst1 (f_inst1()); 
static test& inst2 (f_inst2()); 

उम्मीद है कि दोनों inst1 और f_inst1() बाहर अनुकूलित कर दिया जाएगा।

+0

यह वही तरीका है जिसका मैं उपयोग कर रहा हूं, लेकिन मुझे आश्चर्य है कि एक साफ रास्ता है या नहीं। मैं वैश्विक वस्तुओं जैसे 'std :: cout' या' std :: cin' चाहता हूं क्योंकि यह उदाहरण लौटने वाले फ़ंक्शन से अधिक पठनीय लगता है। – kukyakya

+0

अद्यतन संस्करण देखें। –

+0

शायद वैश्विक संदर्भ चर का प्रयास करें, 'inst1' के उत्थान के लिए आरंभ किया गया? यह भी अनुकूलित किया गया है (एमएसवीसी में) – valdo

2

सी ++ आपको कई फ़ाइलों में वैश्विक वस्तुओं के प्रारंभिकरण के क्रम को प्रबंधित करने के तरीकों की पेशकश नहीं करता है। यदि आपको इन वस्तुओं के प्रारंभिक क्रम के क्रम को व्यवस्थित करने की आवश्यकता है, तो मैं दृढ़ता से आपको पर वैश्विक वस्तुओं की सलाह देता हूं। उन वैश्विक कार्यों को बनाएं जिनमें स्थिर वस्तुएं हों और उन्हें पॉइंटर्स लौटाएं।

लेकिन फिर भी, यह पूर्ण-मैन्युअल प्रारंभिक से कम खतरनाक है। बस उन वस्तुओं को उपलब्ध कुछ पॉइंटर्स बनाएं जिन्हें उनकी आवश्यकता है (अधिमानतः वैश्विक रूप से नहीं), और आप ठीक होंगे।

+0

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

+0

@ कुकायाक्य: फिर आपको इन वस्तुओं को मैन्युअल रूप से प्रारंभ करना होगा। कर्नेल म्यूटेक्स के बिना यह सुनिश्चित करने का यही एकमात्र तरीका है। –

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