2009-02-03 11 views
21

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

for(size_t i = 0; i < 100; ++i) { 
    char *p = new char[123]; 
    if(reinterpret_cast<size_t>(p) % 4) { 
     cout << "*"; 
     system("pause"); 
    } 
    cout << reinterpret_cast<void *>(p) << endl; 
} 
for(size_t i = 0; i < 100; ++i) { 
    short *p = new short[123]; 
    if(reinterpret_cast<size_t>(p) % 4) { 
     cout << "*"; 
     system("pause"); 
    } 
    cout << reinterpret_cast<void *>(p) << endl; 
} 
for(size_t i = 0; i < 100; ++i) { 
    float *p = new float[123]; 
    if(reinterpret_cast<size_t>(p) % 4) { 
     cout << "*"; 
     system("pause"); 
    } 
    cout << reinterpret_cast<void *>(p) << endl; 
} 
system("pause"); 

संकलक मैं उपयोग कर रहा हूँ विजुअल C++ एक्सप्रेस 2008 ऐसा लगता है कि सभी पतों नई लौटे आपरेशन गठबंधन कर रहे हैं। किंतु मुझे यकीन नहीं है। तो मेरा सवाल है: क्या कोई गारंटी है? अगर उनके पास गारंटी है, तो मुझे खुद को संरेखित करने की ज़रूरत नहीं है, अगर नहीं, तो मुझे करना होगा।

उत्तर

19

संरेखण मानक से निम्न गारंटी (3.7.3.1/2) है:

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

संपादित: एक bug जीसीसी में/glibc जहां गारंटी नहीं रखता है पर प्रकाश डाला के लिए timday के लिए धन्यवाद।

EDIT 2: बेन की टिप्पणी एक अंतरंग किनारे के मामले पर प्रकाश डाला गया है। आवंटन दिनचर्या पर आवश्यकताओं केवल मानक द्वारा प्रदान किए गए लोगों के लिए हैं। यदि एप्लिकेशन का अपना संस्करण है, तो परिणाम पर ऐसी कोई गारंटी नहीं है।

+0

सिद्धांत में। अभ्यास में, यदि आप 32-बिट सिस्टम पर जीसीसी + ग्लिब और एसएसई प्रकार का उपयोग कर रहे हैं, तो http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15795 से अवगत रहें। – timday

+0

@ टिमडे: एसएसई प्रकारों के साथ यह समस्या एमएसवीसी ++ (उदाहरण के लिए .NET 2003) के हाल के संस्करणों के बारे में भी सच थी। नवीनतम संस्करण पर परीक्षण नहीं किया है, लेकिन मुझे संदेह है कि यह अभी भी मामला है। –

+0

'ऑपरेटर नया []()' सहायक आवंटन फ़ंक्शन, जो कि आवश्यकता की चिंताओं से लौटाया गया मान, वही सूचक नहीं है जिसे आप 'नए []' ऑपरेटर से प्राप्त करते हैं। यह जवाब गलत है। –

4

प्लेटफ़ॉर्म का नया/नया [] ऑपरेटर पर्याप्त संरेखण के साथ पॉइंटर्स लौटाएगा ताकि यह मूल डेटाटाइप (डबल, फ्लोट इत्यादि) के साथ अच्छा प्रदर्शन करेगा। कम से कम किसी समझदार सी ++ कंपाइलर + रनटाइम को ऐसा करना चाहिए।

यदि आपके पास एसएसई के लिए विशेष संरेखण आवश्यकताएं हैं, तो शायद यह एक अच्छा विचार है विशेष aligned_malloc फ़ंक्शंस का उपयोग करें, या अपना खुद का रोल करें।

4

मैंने एक सिस्टम पर काम किया जहां उन्होंने अपने उपयोग के लिए अजीब बिट को मुक्त करने के लिए संरेखण का उपयोग किया!

उन्होंने वर्चुअल मेमोरी सिस्टम को लागू करने के लिए अजीब बिट का उपयोग किया।

जब एक पॉइंटर के पास थोड़ा सा सेट था, तो उन्होंने यह इंगित करने के लिए उपयोग किया कि यह इंगित करने के लिए उपयोग किया गया है (डेटा बिट घटाएं) डेटाबेस से डेटा प्राप्त करने के लिए डेटा को डेटा नहीं।

मैंने सोचा कि यह कोडिंग का एक कणपूर्ण बुरा बिट है जो अपने स्वयं के अच्छे के लिए चालाक था!

टोनी

+2

उन्हें टैग किए गए पॉइंटर्स कहा जाता है, और वे बिल्कुल असामान्य नहीं हैं। प्रोग्रामिंग भाषा कार्यान्वयन के बहुत सारे एक संकेतक और एक पूर्णांक के बीच अंतर करने के लिए इस चाल का उपयोग करते हैं। – geocar

+1

और एआरएम इंटरैक्टिव इसका उपयोग करता है - जहां लागू हो, एआरएम मोड कोड पते भी हैं, अंगूठे मोड पते अजीब हैं। मैंने एक एवीएल पेड़ कार्यान्वयन देखा है जो नोड के सबट्री के ऊंचाई अंतर को स्टोर करने के लिए नीचे दो बिट्स का उपयोग करता है।सीमित सिस्टम पर, आप जहां भी कर सकते हैं ध्वज बिट्स रख सकते हैं :-) –

+0

मैक ओएस (क्लासिक) के प्रारंभिक संस्करणों पर उन्होंने मेमोरी मैनेजर के लिए शीर्ष 8 बिट्स का उपयोग किया। 68000 के पीटीआर जहां 24 बिट्स का अधिकतम अधिकतम जबकि पता पंजीकृत करता है जहां 32 बिट। – AnthonyLambert

7

संयोग MS documentation malloc/नई लौटने पतों जो 16-बाइट गठबंधन कर रहे हैं के बारे में कुछ का उल्लेख है, लेकिन प्रयोग से यह स्थिति नहीं है। मुझे एक प्रोजेक्ट के लिए 16-बाइट संरेखण की आवश्यकता थी (उन्नत निर्देश सेट के साथ मेमोरी कॉपी को तेज करने के लिए), अंत में मैंने अपना खुद का आवंटन लिखने का प्रयास किया ...-

+0

मुझे तुम्हारा दर्द महसूस होता है ... –

9

यह एक देर से जवाब है लेकिन सिर्फ लिनक्स पर स्थिति स्पष्ट करने 64-बिट सिस्टम पर स्मृति हमेशा 16-बाइट गठबंधन है:

http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html

द्वारा लौटाए गए एक ब्लॉक का पता जीएनयू सिस्टम में मॉलोक या रीयलोक हमेशा आठ (या 64-बिट सिस्टम पर सोलह) में से एक है।

new ऑपरेटर कॉल malloc आंतरिक (देखें ./gcc/libstdc++-v3/libsupc++/new_op.cc) तो यह new करने के साथ ही लागू होता है।

malloc के कार्यान्वयन जो glibc का हिस्सा है मूल रूप से परिभाषित करता है MALLOC_ALIGNMENT होने की 2*sizeof(size_t) और size_t 32 बिट = 4byte और 64 बिट = एक x86-32 और x86-64 प्रणाली, क्रमशः पर 8byte है।

$ cat ./glibc-2.14/malloc/malloc.c: 
... 
#ifndef INTERNAL_SIZE_T 
#define INTERNAL_SIZE_T size_t 
#endif 
... 
#define SIZE_SZ    (sizeof(INTERNAL_SIZE_T)) 
... 
#ifndef MALLOC_ALIGNMENT 
#define MALLOC_ALIGNMENT  (2 * SIZE_SZ) 
#endif 
संबंधित मुद्दे