.init/ .finiघटाया नहीं है। यह अभी भी ईएलएफ मानक का हिस्सा है और मैं कहूंगा कि यह हमेशा के लिए होगा। कोड इन .init/ .finiलोडर / रनटाइम-लिंकर द्वारा चलाया जाता है जब कोड लोड / अनलोड किया जाता है। प्रत्येक ईएलएफ लोड पर (उदाहरण के लिए एक साझा पुस्तकालय) कोड .initचलाया जाएगा। यह उसी तंत्र का उपयोग करना अभी भी संभव है, जैसा कि उसी चीज़ के बारे में प्राप्त करना __attribute__((constructor))/((destructor))। यह पुराना स्कूल है, लेकिन इसके कुछ फायदे हैं।
.ctors/ .dtorsउदाहरण के लिए तंत्र को सिस्टम-आरटीएल / लोडर / लिंकर-स्क्रिप्ट द्वारा समर्थन की आवश्यकता होती है। यह सभी प्रणालियों पर उपलब्ध निश्चित से बहुत दूर है, उदाहरण के लिए गहराई से एम्बेडेड सिस्टम जहां कोड नंगे धातु पर निष्पादित होता है। Ie भले ही __attribute__((constructor))/((destructor))GCC द्वारा समर्थित हो, यह निश्चित नहीं है कि इसे चलाने के लिए लिंकर तक और इसे चलाने के लिए लोडर (या कुछ मामलों में, बूट-कोड) पर चलना होगा। उपयोग करने के लिए .init/ .finiबजाय, सबसे आसान तरीका लिंकर झंडे का उपयोग करना है: -init -fini (यानी जीसीसी कमांड लाइन से, सिंटैक्स होगा -Wl -init my_init -fini my_fini)।
दोनों तरीकों का समर्थन करने वाले सिस्टम पर, एक संभावित लाभ यह है कि कोड .initपहले चलाया जाता है .ctorsऔर .finiबाद में कोड .dtors। यदि आदेश प्रासंगिक है तो कम से कम एक क्रूड लेकिन आसान तरीका है जो इनिट / एग्जिट फ़ंक्शंस के बीच अंतर करता है।
एक बड़ी कमी यह है कि आप आसानी से प्रत्येक लोड करने योग्य मॉड्यूल के प्रति एक _initऔर एक से अधिक _finiकार्य नहीं कर सकते हैं और संभवतः .soप्रेरित से अधिक में कोड को टुकड़े करना होगा । एक और यह है कि ऊपर वर्णित लिंकर विधि का उपयोग करते समय, कोई मूल _init और _finiडिफ़ॉल्ट फ़ंक्शन (द्वारा प्रदान crti.o) को प्रतिस्थापित करता है । यह वह जगह है जहां आमतौर पर सभी प्रकार के आरम्भिकरण होते हैं (लिनक्स पर यह वह जगह है जहाँ वैश्विक चर असाइनमेंट को आरंभीकृत किया जाता है)। चारों ओर एक रास्ता यहाँ वर्णित है
ऊपर दिए गए लिंक में ध्यान दें कि मूल _init()में कैस्केडिंग की आवश्यकता नहीं है क्योंकि यह अभी भी जगह में है। callइनलाइन विधानसभा तथापि में 86-स्मरक और एक समारोह विधानसभा (उदाहरण के लिए एआरएम) की तरह कई अन्य आर्किटेक्चर के लिए पूरी तरह से अलग दिखेगा से फोन कर रहा है। Ie कोड पारदर्शी नहीं है।
.init/ .finiऔर .ctors/ .detorsतंत्र समान हैं, लेकिन काफी नहीं। में कोड .init/ .finiरन "जैसा है"। यानी आपके पास .init/ में कई कार्य हो सकते हैं .fini, लेकिन कई छोटी .soफ़ाइलों में कोड को तोड़ने के बिना पूरी तरह से पारदर्शी सी में उन्हें पूरी तरह से पारदर्शी रूप से वहां रखना मुश्किल है ।
.ctors/ .dtorsसे अलग आयोजित किए जाते हैं .init/ .fini। .ctors/ .dtorsअनुभाग दोनों फ़ंक्शन के साथ संकेत के साथ सिर्फ टेबल हैं, और "कॉलर" एक सिस्टम-प्रदत्त लूप है जो प्रत्येक फ़ंक्शन को अप्रत्यक्ष रूप से कॉल करता है। यानी लूप-कॉलर आर्किटेक्चर विशिष्ट हो सकता है, लेकिन जैसा कि यह सिस्टम का हिस्सा है (यदि यह सभी पर मौजूद है) तो कोई फर्क नहीं पड़ता।
निम्नलिखित स्निपेट .ctorsफ़ंक्शन सरणी में नए फ़ंक्शन पॉइंटर्स जोड़ता है , मुख्य रूप से उसी तरह से __attribute__((constructor))होता है (विधि के साथ सह-अस्तित्व हो सकता है) __attribute__((constructor)))।
#define SECTION( S ) __attribute__ ((section ( S )))
void test(void) {
printf("Hello\n");
}
void (*funcptr)(void) SECTION(".ctors") =test;
void (*funcptr2)(void) SECTION(".ctors") =test;
void (*funcptr3)(void) SECTION(".dtors") =test;
एक फ़ंक्शन पॉइंटर्स को एक पूरी तरह से अलग-अलग स्व-आविष्कृत अनुभाग में भी जोड़ सकता है। एक संशोधित लिंकर स्क्रिप्ट और लोडर .ctors/ .dtorsलूप की नकल करने वाले एक अतिरिक्त फ़ंक्शन की आवश्यकता होती है। लेकिन इसके साथ ही कोई भी निष्पादन आदेश पर बेहतर नियंत्रण प्राप्त कर सकता है, इन-तर्क और रिटर्न कोड हैंडलिंग एटा (उदाहरण के लिए एक C ++ परियोजना में, यह वैश्विक निर्माणकर्ताओं के पहले या बाद में चलने वाली किसी चीज़ की आवश्यकता में उपयोगी होगा)।
__attribute__((constructor))/((destructor))जहां संभव हो, मैं पसंद करूंगा , यह एक सरल और सुरुचिपूर्ण समाधान है यहां तक कि यह धोखा देने जैसा लगता है। अपने जैसे नंगे-धातु कोडर के लिए, यह हमेशा एक विकल्प नहीं है।
पुस्तक लिंकर्स और लोडर में कुछ अच्छे संदर्भ ।
#define __attribute__(x)) के लिए आसान बनाते हैं । यदि आपके पास कई गुण हैं, उदाहरण के लिए__attribute__((noreturn, weak)), यह "मैक्रो आउट" के लिए कठिन होगा यदि केवल ब्रैकेट्स का एक सेट था।