स्थिर int arr [10] मेमोरी एड्रेस हमेशा 060 में समाप्त होता है


17

मेरे पास एसी प्रोग्राम है जो इस तरह दिखता है

main.c

#include <stdio.h>
#define SOME_VAR 10

static int heap[SOME_VAR];


int main(void) {
    printf("%p", heap);
    return 0;
}

और जब मैं संकलित कार्यक्रम को कुछ बार चलाता हूं तो यह आउटपुट करता है

0x58aa7c49060
0x56555644060
0x2f8d1f8e060
0x92f58280060
0x59551c53060
0xd474ed6e060
0x767c4561060
0xf515aeda060
0xbe62367e060

यह हमेशा 060 में क्यों समाप्त होता है? और ढेर में संग्रहीत सरणी है?

संपादित करें: मैं लिनक्स पर हूं और मेरे पास एएसएलआर है। मैंने gcc का उपयोग करके कार्यक्रम संकलित किया


2
क्या ऑपरेटिंग सिस्टम? क्या संकलक?
एंड्रयू हेनले

2
वेरिएबल ढेर में नहीं है, यह प्रोग्राम के एड्रेस स्पेस के डेटा या bss सेक्शन में है, en.wikipedia.org/wiki/Static_variable देखें । मेरा अनुमान है कि कार्यक्रम को हमेशा एक निश्चित सीमा पर एक स्मृति पते पर रखा जाएगा, उदाहरण के लिए 0x1000 द्वारा विभाजित किया जा सकता है, और प्रोग्राम के पता स्थान में निश्चित ऑफसेट पर चर को संकलक द्वारा रखा जाता है।
बोडो

जवाबों:


15

पते ASLR (पता स्थान लेआउट ramdomization) के कारण भिन्न होते हैं। इसका उपयोग करके, बाइनरी को वर्चुअल एड्रेस स्पेस में विभिन्न स्थानों पर मैप किया जा सकता है।

चर heapहै - इसके नाम के विपरीत - ढेर पर स्थित नहीं है, लेकिन पर bss। पता स्थान में ऑफसेट इसलिए स्थिर है।

पेज ग्रैन्युलैरिटी पर मैप किए जाते हैं, जो कई प्लेटफार्मों पर 4096 बाइट्स (हेक्स: 0x1000) हैं। यही कारण है कि, पता के अंतिम तीन हेक्स अंक समान हैं।

जब आपने स्टैक वैरिएबल के साथ ऐसा ही किया था , तो पता कुछ प्लेटफार्मों पर अंतिम अंकों में भी भिन्न हो सकता है (अर्थात् हाल की गुठली के साथ लिनक्स), क्योंकि स्टैक न केवल कहीं और मैप किया जाता है, बल्कि स्टार्टअप पर एक यादृच्छिक ऑफसेट भी प्राप्त करता है।


ASLR मुझे याद रखने के रूप में लोडिंग के आधार को यादृच्छिक बनाता है। अनुभाग का पता उस पते पर आधारित होता है।
अफशिन

मैं एक्सल-थोबियास श्रेएन द्वारा ऑब्जेक्ट ओरिएंटेड एएनएसआई-सी प्रोग्रामिंग पर एक पुस्तक का उपयोग कर रहा हूं। पुस्तक 1993 की तरह कुछ में लिखी गई है। क्या आपको पता है कि मेमोरी लेआउट अलग था? यदि यह नहीं था, तो heapजब वह ढेर में नहीं होता तो उसने चर का नाम क्यों दिया होगा ?
linuxlmao

क्या 4096 किसी तरह से 060 में अनुवाद करता है या 0x1000 060 में अनुवाद करता है अन्यथा मुझे यह समझ में नहीं आता है कि आपके द्वारा समाप्त होने का कारण क्या है? मुझे लगा कि इसे सरणी के आकार के साथ कुछ ऐसा करना पड़ सकता है जो हेक्साडेसिमल से 060 में अनुवादित है, जैसे दशमलव
linuxlmao

2
@linuxlmao ऑफ़सेट उदाहरण के लिए 14060 है, इसलिए जब आप एक पृष्ठ आकार (0x1000) के कई जोड़ते हैं, तो अंतिम तीन अंक बने रहते हैं 060
23

4

यदि आप Windows का उपयोग कर रहे हैं, तो इसका कारण PE संरचना है।

आपका heapचर .dataफ़ाइल के अनुभाग में संग्रहीत किया जाता है और इसका पता इस खंड की शुरुआत के आधार पर लगाया जाता है। प्रत्येक अनुभाग एक पते में स्वतंत्र रूप से लोड किया गया है, लेकिन इसका प्रारंभिक पता पृष्ठ आकार का एक से अधिक है। चूँकि आपके पास कोई अन्य चर नहीं है .data, इसलिए इसका पता संभवत: खंड का प्रारंभ है , इसलिए इसका पता कई आकार का होगा।

उदाहरण के लिए, यह आपके कोड के संकलित Windows संस्करण की मेज है: खंड अपने संकलित कोड है और थे अपने शामिल चर। जब आपके पीई को मेमोरी में लोड किया जाता है, तो अनुभाग अलग-अलग पते में लोड किए जाते हैं और जो कि वापस आ जाता है और पृष्ठ आकार के कई हो जाएगा। लेकिन प्रत्येक चर का पता उस खंड की शुरुआत के सापेक्ष होता है जो अब एक पृष्ठ आकार है। इसलिए आपको हमेशा कम अंकों पर एक निश्चित संख्या दिखाई देगी। चूँकि अनुभाग के प्रारंभ से संबंधित पता संकलक, संकलन विकल्प, आदि पर आधारित है, इसलिए आपको एक ही कोड से अलग-अलग संख्याएँ दिखाई देंगी, लेकिन अलग-अलग संकलक, लेकिन हर बार जो छपेगा वह निश्चित है।वर्गों.text.dataheapVirtualAlloc()heap

जब मैं कोड संकलित करता हूं, तो मैंने देखा heapकि खंड की 0x8B0शुरुआत के बाद बाइट पर रखा गया है .data। इसलिए हर बार जब मैं इस कोड को चलाता हूं, तो मेरा पता समाप्त हो जाता है 0x8B0


मैं एक्सल-थोबियास श्रेएन द्वारा ऑब्जेक्ट ओरिएंटेड एएनएसआई-सी प्रोग्रामिंग पर एक पुस्तक का उपयोग कर रहा हूं। पुस्तक 1993 की तरह कुछ में लिखी गई है। क्या आपको पता है कि मेमोरी लेआउट अलग था? यदि यह नहीं था, तो heapजब वह ढेर में नहीं होता तो उसने चर का नाम क्यों दिया होगा ?
linuxlmao

2
@linuxlmao यह अच्छी तरह से अलग हो सकता है। 1993 में, विंडोज एक 16-बिट ऑपरेटिंग सिस्टम था, जिसमें मेमोरी सेगमेंटेशन और सभी प्रकार के भ्रमित सामान थे। यह था नहीं एक 32-बिट, फ्लैट स्मृति वास्तुकला के रूप में यह अब है। लेकिन इस प्रकार की चीजें इसीलिए हैं कि मेमोरी में प्रोग्राम बाइनरी के लेआउट के बारे में सामान्य प्रश्न पूछना / उत्तर देना उपयोगी नहीं है। समझें कि सी भाषा मानक आपको सामान्य रूप से क्या गारंटी देता है , और आपको यह जानने की आवश्यकता है। केवल वास्तविक लेआउट के बारे में चिंता आप एक विशिष्ट समस्या को दूर करने रहे हैं, तो एक डिबगर का उपयोग
कोड़ी ग्रे

नहीं, पुराने सिस्टम पर भी चर को ढेर पर नहीं बनाया जाना चाहिए क्योंकि यह
मॉलोक के

@Ashshin मैं ऊपर ओपी की टिप्पणी को संबोधित कर रहा हूँ
phuclv

@phuclv क्षमा करें, क्योंकि आप उसका उल्लेख नहीं कर रहे थे, मुझे लगा कि आप मुझे संबोधित कर रहे हैं। :)
अफशीन

4

कंपाइलर के पास heapएक डेटा सेगमेंट में ऑफसेट 0x60 बाइट्स में डालने के लिए हुआ , संभवतः क्योंकि कंपाइलर के पास पहले 0x60 बाइट्स में कुछ अन्य सामान हैं, जैसे कि रूट द्वारा शुरू किए गए कोड द्वारा उपयोग किए गए डेटा main। यही कारण है कि आप "060" देखते हैं; यह वही है जहाँ यह हुआ था, और इसका कोई बहुत महत्व नहीं है।

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

परिभाषा स्थिर भंडारण अवधि के साथ static int heap[SOME_VAR];परिभाषित करती है heap। विशिष्ट सी कार्यान्वयन इसे सामान्य डेटा अनुभाग में संग्रहीत करते हैं, न कि ढेर में। "हीप" मेमोरी के लिए एक मिथ्या नाम है जो गतिशील आवंटन के लिए उपयोग किया जाता है। (यह एक मिथ्या नाम है क्योंकि mallocकार्यान्वयन डेटा संरचनाओं और एल्गोरिदम की एक किस्म का उपयोग कर सकते हैं, ढेर तक सीमित नहीं हैं। वे एक कार्यान्वयन में कई तरीकों का उपयोग भी कर सकते हैं।)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.