2012-01-04 6 views
5

मैं निम्नलिखित आज के समान कोड भर में आया था और मैं के रूप में उत्सुक हूँ क्या वास्तव में क्या हो रहा है:निष्पादन क्षेत्रों और इनपुट अनुभागों का अतिसंवेदनशीलता क्या है?

#pragma pack(1) 
__align(2) static unsigned char multi_array[7][24] = { 0 }; 
__align(2) static unsigned char another_multi_array[7][24] = { 0 }; 
#pragma pack() 

जब Keil संकलक में __align कीवर्ड के लिए एक संदर्भ के लिए खोज, मैं इस पार आया:

निष्पादन क्षेत्रों और इनपुट वर्गों के Overalignment वहां स्थितियों जब आप कोड और डेटा वर्गों overalign करने के लिए ... आप मूल स्रोत कोड के लिए उपयोग किया है, तो आप __align साथ संकलन समय पर ऐसा कर सकते हैं (एन चाहते हैं) कीवर्ड ...

मुझे समझ में नहीं आता कि "ओवरलैगिंग कोड और डेटा अनुभाग" का क्या अर्थ है। क्या कोई यह स्पष्ट करने में मदद कर सकता है कि यह अतिसंवेदनशीलता कैसे होती है?

+1

ओवरलैमेंट एआरएम पर उपयोगी हो सकता है। "लोड तत्काल" (एमओवी) निर्देश पूरे 32-बिट मान को लोड नहीं कर सकता है। इसके बजाय यह एक समय में 8 बिट्स लोड कर सकता है, किसी भी स्थिति में घूमता है। इस कारण से, आपका कोड अधिक शून्य बिट्स में पते को समाप्त करने का प्रयास कर रहा है, जिससे संकलित कोड को पॉइंटर मान लोड करने में आसान/तेज़ बना दिया जा सकता है। –

उत्तर

6

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

संकलक आमतौर पर डेटा में अंतर को पेश करके ऐसा करता है; char के लिए एक बाइट, भराव की तीन बाइट्स तो int सही गठबंधन है, और चार बाइट्स int खुद के लिए: उदाहरण के लिए, एक char एक 32-बिट int द्वारा पीछा के साथ एक struct, एक ऐसी प्रणाली पर, आठ बाइट्स की आवश्यकता होगी ।

डेटा को ओवरलैग करने के लिए संकलक स्वाभाविक रूप से प्रदान करने से अधिक संरेखण का अनुरोध करना है। उदाहरण के लिए, आप अनुरोध कर सकते हैं कि एक 32-बिट पूर्णांक 8-बाइट सीमा पर शुरू होता है, यहां तक ​​कि 4-बाइट शब्दों का उपयोग करने वाली प्रणाली पर भी। (ऐसा करने का एक प्रमुख कारण यह होगा कि यदि आप 8-बाइट शब्दों का उपयोग करने वाली प्रणाली के साथ बाइट-स्तरीय इंटरऑपरेबिलिटी का लक्ष्य रखते हैं: यदि आप एक सिस्टम से दूसरी प्रणाली में struct एस पास करते हैं, तो आप दोनों प्रणालियों में एक ही अंतराल चाहते हैं।)

+0

तो एक बहुआयामी सरणी के मामले में एक हस्ताक्षरित चार (उपरोक्त उदाहरण की तरह) के रूप में घोषित किया गया है, क्या प्रत्येक _element_ दो बाइट्स को संरेखित करेगा? –

+0

@embedded_guy: नहीं, केवल परिवर्तनीय, यानी, संपूर्ण रूप से सरणी है; चूंकि यह एक-बाइट तत्वों की एक सरणी है, इसलिए इसे सामान्य रूप से किसी भी संरेखण की आवश्यकता नहीं होती है, लेकिन '__align (2)' अनुरोध जो दो-बाइट सीमा से शुरू होते हैं। प्रत्येक तत्व को दो बाइट्स में संरेखित करना संभव नहीं है, क्योंकि तब सरणी का उपयोग करने वाले किसी भी क्लाइंट को यह जानना होगा। ('स्ट्रक्चर' प्रकार घोषित करते समय, आप अलग-अलग फ़ील्ड को संरेखित कर सकते हैं क्योंकि 'स्ट्रक्चर' का उपयोग करने वाले किसी भी व्यक्ति को हमेशा 'ऑफसेट' की ज़रूरत होती है, लेकिन सरणी के लिए, नियमित पॉइंटर अंकगणित का उपयोग किया जाता है।) – ruakh

+0

@downvoter: समझाने की देखभाल? – ruakh

5

ओवरलैलाइन द्वारा, केइल का मतलब किसी ऑब्जेक्ट को डेटा प्रकार की आवश्यकता के मुकाबले एक बड़ी संरेखण सीमा में संरेखित करने से अधिक जटिल नहीं है।

__align के लिए प्रलेखन देखें: "आप केवल ओवरलाइन कर सकते हैं। यानी, आप दो-बाइट ऑब्जेक्ट चार-बाइट गठबंधन कर सकते हैं लेकिन आप चार बाइट ऑब्जेक्ट को 2 बाइट्स पर संरेखित नहीं कर सकते हैं।"

लिंकर के मामले में, आप ALIGNALL या OVERALIGN निर्देशों का उपयोग करके अन्य बाइनरी मॉड्यूल के भीतर अनुभागों पर अतिरिक्त संरेखण को मजबूर कर सकते हैं। यह प्रदर्शन कारणों से उपयोगी हो सकता है, लेकिन यह एक आम परिदृश्य नहीं है।

4

ओवरलिग्निमेंट तब होता है जब डेटा को इसके डिफ़ॉल्ट संरेखण से अधिक गठबंधन किया जाता है। उदाहरण के लिए, 4-बाइट int में आमतौर पर 4 बाइट्स का डिफ़ॉल्ट संरेखण होता है। (जिसका अर्थ है कि पता 4 से विभाजित होगा)

डेटाटाइप का डिफ़ॉल्ट संरेखण डेटाटाइप का आकार अक्सर (लेकिन हमेशा नहीं) होता है।

ओवरलैग्मेंटमेंट आपको इस संरेखण को डिफ़ॉल्ट से अधिक कुछ में बढ़ाने की अनुमति देता है।


कारण है कि आप ऐसा करना चाहते हैं हैं के लिए के रूप में: इस के लिए

एक कारण यह सक्षम पहुँच एक बड़ा डेटाप्रकार साथ डेटा (कि एक बड़ा संरेखण है) हो रहा है।

उदाहरण के लिए:

char buffer[16]; 

int *ptr = (int*)&buffer; 

ptr[0] = 1; 
ptr[1] = 2; 

डिफ़ॉल्ट रूप से, बफर केवल 1 बाइट के लिए गठबंधन किया जाएगा। हालांकि, int को 4-बाइट संरेखण की आवश्यकता है। यदि buffer को 4 बाइट्स के साथ गठबंधन नहीं किया गया है, तो आपको एक गलत संरेखण अपवाद मिलेगा। (AFAIK, एआरएम गलत संरेखित स्मृति उपयोग की अनुमति नहीं है ... 86/64 आम तौर पर करता है, लेकिन प्रदर्शन की सजा के साथ)

__align() आप मजबूर संरेखण उच्च यह काम करने के लिए करने देगा:

__align(4) char buffer[16]; 

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

+0

डाउनवोट की व्याख्या करने की देखभाल? मैंने गलत क्या कहा? – Mysticial

+0

सुनिश्चित नहीं है कि किसने डाउनवॉट किया। मैंने आपका जवाब उपयोगी पाया और इसे एक अपवित्र दिया। 'Int * ptr = (int *) और buffer' के साथ अच्छे उदाहरण के लिए –

+0

+1। (और अनाम डाउनवॉटर को रद्द करने के लिए।) – ruakh

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