2013-04-20 12 views
6

में सी मेमोरी प्रबंधन मैं उबंटू 12.10 x86_64 पर जीसीसी संस्करण 4.7.2 का उपयोग कर रहा हूं।जीसीसी

इन सभी मेरी टर्मिनल पर डेटा प्रकार के आकार हैं की

पहले:

sizeof(char) = 1  

sizeof(short) = 2   sizeof(int) = 4 
sizeof(long) = 8   sizeof(long long) = 8 

sizeof(float) = 4   sizeof(double) = 8 
sizeof(long double) = 16 

अब कृपया इस कोड स्निपेट पर एक नजर है: अगर मैं गलत नहीं हूँ हम कर सकते हैं

int main(void) 
{ 
    char c = 'a'; 
    printf("&c = %p\n", &c); 
    return 0; 
} 

' c के पते के बारे में कुछ भी भविष्यवाणी नहीं करते हैं। लेकिन प्रत्येक बार यह प्रोग्राम f में समाप्त होने वाले कुछ यादृच्छिक हेक्स पते देता है। तो अगला उपलब्ध स्थान कुछ हेक्स मान 0 में समाप्त होगा। मैंने अन्य डेटा प्रकारों के मामले में भी इस पैटर्न को देखा। एक int मान के लिए पता कुछ हेक्स मान c में समाप्त होता था। डबल के लिए यह कुछ यादृच्छिक हेक्स मान 8 में समाप्त होता था और इसी तरह।

तो मेरे यहां 2 प्रश्न हैं।

1) इस तरह के स्मृति आवंटन को किसने नियंत्रित किया है? क्या यह जीसीसी या सी मानक है?

2) जो भी हो, ऐसा क्यों है? चर को इस तरह से संग्रहीत क्यों किया जाता है कि अगली उपलब्ध स्मृति स्थान 0 में समाप्त होने वाले हेक्स मान पर शुरू होता है? कोई विशिष्ट लाभ?

int main(void) 
{ 
    double a = 10.2; 
    int b = 20; 
    char c = 30; 
    short d = 40; 

    printf("&a = %p\n", &a); 
    printf("&b = %p\n", &b); 
    printf("&c = %p\n", &c); 
    printf("&d = %p\n", &d); 

    return 0; 
} 

अब यहाँ मैं क्या देखा मेरे लिए पूरी तरह से नया है:

अब कृपया इस कोड स्निपेट पर एक नजर है। मैंने सोचा कि वेरिएबल उसी क्रम में संग्रहीत किया जाएगा जिसे वे घोषित कर रहे हैं। लेकिन नहीं! ऐसा नहीं है। यहाँ एक यादृच्छिक वार्तालाप में से एक का नमूना उत्पादन होता है:

&a = 0x7fff8686a698 
&b = 0x7fff8686a694 
&c = 0x7fff8686a691 
&d = 0x7fff8686a692 

ऐसा लगता है कि चर उनके आकार के बढते क्रम में हल कर पाने और उसके बाद वे एक ही क्रमबद्ध क्रम में, लेकिन पिछले यानी अवलोकन 1. बनाए रखने के साथ जमा हो जाती है चर (सबसे बड़ा एक) इस तरह से संग्रहीत हो जाता है कि अगली उपलब्ध स्मृति स्थान 0 में समाप्त होने वाला हेक्स मान है।

यहां मेरे प्रश्न हैं:

3) इसके पीछे कौन है? क्या यह जीसीसी या सी मानक है?

4) पहले चर को क्रमबद्ध करने में समय बर्बाद क्यों करें और फिर 'पहले आओ पहले सेवा' आधार पर स्मृति आवंटित करने के बजाय स्मृति आवंटित क्यों करें? इस प्रकार के सॉर्टिंग का कोई विशिष्ट लाभ और फिर स्मृति आवंटित करना?

int main(void) 
{ 
    char array1[] = {1, 2}; 
    int array2[] = {1, 2, 3}; 

    printf("&array1[0] = %p\n", &array1[0]); 
    printf("&array1[1] = %p\n\n", &array1[1]); 

    printf("&array2[0] = %p\n", &array2[0]); 
    printf("&array2[1] = %p\n", &array2[1]); 
    printf("&array2[2] = %p\n", &array2[2]); 

    return 0; 
} 

अब यह भी मेरे लिए चौंकाने वाला है:

अब कृपया इस कोड स्निपेट पर एक नजर है।

: क्या मैंने देखा है, तो elements of an array >= 2 और निम्न अगर elements < 2 तो यह स्मृति स्थान हो जाता है अवलोकन 1.

तो यहाँ मेरे सवालों हैं कि सरणी हमेशा कुछ यादृच्छिक हेक्स मान '0' में समाप्त होने पर संग्रहीत किया जाता है है 5) इस यादृच्छिक हेक्स मान पर 0 चीज़ पर समाप्त होने वाले सरणी को संग्रहीत करने के पीछे कौन है? क्या यह जीसीसी या सी मानक है?

6) अब स्मृति को बर्बाद क्यों करें? मेरा मतलब है array2array1 के बाद तुरंत संग्रहीत किया जा सकता था (और इसलिए array2 में स्मृति स्थान 2 पर समाप्त होगा)। लेकिन array2 के बजाय 0 पर समाप्त होने वाले अगले हेक्स मान पर संग्रहीत किया जाता है जिससे 14 मेमोरी स्थानों को बीच में छोड़ दिया जाता है। कोई विशिष्ट लाभ?

+2

कोई "मानक" वास्तव में शामिल नहीं है। यह इस्तेमाल किए गए कंपाइलर के संस्करण पर निर्भर हो सकता है, एबीआई, कर्नेल, जिस वातावरण में आप उस प्रोग्राम को चलाते हैं, आदि। एबीआई शायद यह अनिवार्य है कि स्टैक पॉइंटर 16 बाइट्स गठबंधन है, और कंपाइलर ने चर के रूप में " यह चाहता है "। और 'array2' शब्द-संरेखित होना चाहिए (4 बाइट्स के एकाधिक) जबकि 'array1' होने की आवश्यकता नहीं है ... –

+1

गलियारे के इस तरफ कमरे की संख्या क्यों * सभी * हैं? गलियारे के विपरीत तरफ कमरे की संख्या सभी * विषम * क्यों हैं? – wildplasser

+0

आप वास्तव में क्यों पूछते हैं? आपके प्रश्न के पीछे क्या कारण है, और आप वास्तव में क्यों परवाह करेंगे? (आपको कोड प्रोग्राम नहीं करना चाहिए जो इस के सटीक कारण पर इतने भारी निर्भर हैं)। –

उत्तर

5

कारणों का एक हिस्सा आपके सिस्टम & प्रोसेसर के लिए application binary interface (एबीआई) विनिर्देशों द्वारा अनिवार्य है।

x86 calling conventions और SVR4 x86-64 ABI supplement देखें (मैं हाल की प्रतिलिपि का यूआरएल दे रहा हूं; नवीनतम मूल वेब पर खोजने के लिए आश्चर्यजनक रूप से कठिन है)।

किसी दिए गए कॉल फ्रेम के भीतर, कंपाइलर मनमाने ढंग से स्टैक स्लॉट में चर रख सकता है। यह इच्छा पर स्टैक को पुनर्गठित करने के लिए (ऑप्टिमाइज़ करने पर) कोशिश कर सकता है, उदा। संरेखण बाधाओं को कम करके। आपको इसके बारे में चिंता नहीं करनी चाहिए।

एक कंपाइलर उपयुक्त संरेखण के साथ स्टैक स्थान पर स्थानीय चर डालने का प्रयास करता है। जीसीसी के alignof एक्सटेंशन देखें। जहां वास्तव में कंपाइलर इन चरों को डालता है, महत्वपूर्ण नहीं है, my answer here देखें। (यदि यह आपके कोड के लिए महत्वपूर्ण है, तो आपको वास्तव में एक सामान्य स्थानीय struct में चर पैक करना चाहिए, क्योंकि प्रत्येक कंपाइलर, संस्करण और अनुकूलन झंडे अलग-अलग चीजें कर सकते हैं, इसलिए अपने विशेष कंपाइलर के उस सटीक व्यवहार पर निर्भर न हों)।

7

वह पता जिस पर स्टैक और ढेर शुरू होता है ऑपरेटिंग सिस्टम द्वारा प्रक्रिया को दिया जाता है। संकलन समय पर ज्ञात ऑफसेट्स का उपयोग करके, बाकी सब कुछ संकलक द्वारा तय किया जाता है। इनमें से कुछ चीजें आपके लक्षित वास्तुकला में मौजूद एक मौजूदा सम्मेलन का पालन कर सकती हैं और इनमें से कुछ नहीं हैं।

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

+0

तो जीसीसी सभी उपरोक्त 3 अवलोकनों के पीछे है। ठीक। तो यह सवाल 1), 3) और 5)। और कंपाइलर इस तरह के आवंटन को लाने के समय को कम करने के लिए करता है। लेकिन यह शांत सामान्य बयान है। 1) मेरा मतलब है कि यह कंपाइलर की मदद कैसे करता है यदि चर आकार उनके क्रम के क्रम में क्रमबद्ध होते हैं और फिर स्मृति आवंटित करते हैं? 2) यह कैसे लाने के समय को कम करता है या जो भी लाभ होता है, यदि चर इन्हें इस तरह से संग्रहीत किया जाता है कि अगली उपलब्ध स्मृति स्थान कुछ यादृच्छिक हेक्स मान '0' पर समाप्त हो रहा है? – rootkea

+2

@rootkea - ऐसा होता है कि आपके प्रोसेसर (x86) पर डेटा लाने से सबसे तेज़ होता है यदि पता डेटा आकार का भी एक से अधिक है। इस तरह से जानकारी बिट्स को सॉर्ट करने के लिए आवश्यक संभावित देरी के बिना हार्डवेयर में सीधे आगे बढ़ सकती है। उदाहरण के लिए, यदि आपका 'डबल' 4 में समाप्त होने वाले पते पर है, तो प्रोसेसर को दो 64-बिट शब्दों को पढ़ना पड़ सकता है और प्रत्येक पढ़ने से चार बाइट चुन सकते हैं। इसमें कुछ अतिरिक्त समय लग सकता है। –

+0

सी मानक यह निर्धारित नहीं करता है कि स्वचालित चर को ढेर पर आवंटित किया जाता है। ज्यादातर मामलों में वे हैं, लेकिन उन्हें जरूरत नहीं है। – wildplasser