स्थैतिक स्मृति आवंटन और गतिशील स्मृति आवंटन के बीच अंतर


94

मैं जानना चाहूंगा कि स्टैटिक मेमोरी एलोकेशन और डायनेमिक मेमोरी एलोकेशन में क्या अंतर है?

क्या आप इसे किसी भी उदाहरण के साथ समझा सकते हैं?

जवाबों:


90

तीन प्रकार के आवंटन हैं - स्थैतिक, स्वचालित और गतिशील।

स्टेटिक आवंटन का मतलब है, कि प्रोग्राम शुरू होने पर आपके वेरिएबल्स के लिए मेमोरी आवंटित की जाती है। जब प्रोग्राम बनाया जाता है तो आकार निश्चित होता है। यह वैश्विक चरों पर लागू होता है, फ़ाइल स्कोप वैरिएबल, और वैरिएबल staticफंक्शन्स के साथ योग्य होते हैं।

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

void func() {
    int i; /* `i` only exists during `func` */
}

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

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

ऊपरी उदाहरण में, आवंटित स्मृति अभी भी वैध और सुलभ है, भले ही फ़ंक्शन समाप्त हो गया हो। जब आप स्मृति के साथ किया जाता है, तो आपको इसे मुक्त करना होगा:

free(mem);

2
यकीन है कि चर के जीवनकाल पर आपका नियंत्रण है ... आप गुंजाइश तय कर रहे हैं, है ना?
लुचियन ग्रिगोर

बेशक, लेकिन यह वह नहीं है जो मेरा मतलब था। आप इसके दायरे को रेखांकित करने के लिए चर के जीवनकाल का विस्तार नहीं कर सकते हैं। लेकिन शायद मुझे अपने उत्तर में स्पष्ट करना चाहिए। धन्यवाद
कांस्टेंटिनियस

5
-1 यह उत्तर गलत है। आप स्थैतिक और स्वचालित चर को भ्रमित करते हैं ।
ब्रिस

2
आपका अपना वाक्य पढ़ता है: " स्टेटिक आवंटन का मतलब है, कि आपके चर के लिए मेमोरी स्वचालित रूप से आवंटित की गई है" यह गलत हैजीएनयू के परिवाद के मैनुअल पेज के बारे में क्या कहना है, इस पर एक नज़र डालें ।
ब्रिस

1
@EliBendersky अब इसे पुनःप्रकाशित किया गया है। अगर यह अभी है तो जाँच करें।
सूरज जैन

115

यह एक मानक साक्षात्कार प्रश्न है:

गतिशील स्मृति आवंटन

स्मृति रनटाइम का उपयोग कर आवंटित किया गया है calloc(), malloc()और दोस्तों। इसे कभी-कभी 'हीप' मेमोरी के रूप में भी जाना जाता है, हालांकि इसका ढेर डेटा-संरचना रेफ के साथ कोई लेना-देना नहीं है ।

int * a = malloc(sizeof(int));

हीप मेमोरी तब तक लगातार बनी रहती है जब तक free()कि उसे कहा नहीं जाता दूसरे शब्दों में, आप चर के जीवनकाल को नियंत्रित करते हैं।

स्वचालित मेमोरी आवंटन

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

int a = 43;

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

स्थैतिक स्मृति आवंटन

संकलन समय * पर आबंटित किया जाता है , और स्थिर स्मृति में एक चर का जीवनकाल कार्यक्रम का जीवनकाल होता है

C में, स्थिर मेमोरी को staticकीवर्ड का उपयोग करके आवंटित किया जा सकता है । दायरा केवल संकलन इकाई है।

जब externकीवर्ड माना जाता है तो चीजें अधिक दिलचस्प हो जाती हैं । जब एक externचर को परिभाषित किया जाता है तो संकलक इसके लिए मेमोरी आवंटित करता है। जब एक externचर घोषित किया जाता है , तो संकलक के लिए आवश्यक है कि चर को अन्यत्र परिभाषित किया जाए। externचरों को घोषित / परिभाषित करने में विफलता के कारण लिंकिंग समस्याएं होंगी, जबकि staticचरों को घोषित / परिभाषित करने में विफलता संकलन समस्याओं का कारण होगी।

फ़ाइल स्कोप में, स्थिर कीवर्ड वैकल्पिक है (फ़ंक्शन के बाहर):

int a = 32;

लेकिन फंक्शन स्कोप में नहीं (फंक्शन के अंदर):

static int a = 32;

तकनीकी रूप से, externऔर staticसी में चर के दो अलग-अलग वर्ग हैं।

extern int a; /* Declaration */
int a; /* Definition */

* स्थिर मेमोरी आवंटन पर नोट्स

यह कहना कुछ भ्रामक है कि स्थिर मेमोरी को संकलन समय पर आवंटित किया जाता है, खासकर अगर हम यह विचार करना शुरू कर दें कि संकलन मशीन और होस्ट मशीन समान नहीं हो सकती है या समान आर्किटेक्चर पर भी नहीं हो सकती है।

यह सोचना बेहतर होगा कि स्थिर मेमोरी का आवंटन संकलक द्वारा संकलित किया जाता है बजाय संकलन समय पर आवंटित किए

उदाहरण के लिए संकलक dataबाइनरी में एक बड़ा खंड बना सकता है और जब प्रोग्राम को मेमोरी में लोड किया जाता है, तो उसके भीतर का पताdataकार्यक्रम का खंड आवंटित स्मृति के स्थान के रूप में उपयोग किया जाएगा। यह संकलित बाइनरी को बहुत बड़ा बनाने का चिह्नित नुकसान है अगर बहुत अधिक स्थिर मेमोरी का उपयोग करता है। कोड की आधा दर्जन से कम लाइनों से उत्पन्न एक बहु-गीगाबाइट बाइनरी लिखना संभव है। एक अन्य विकल्प कंपाइलर के लिए इनिशियल कोड को इंजेक्ट करना है जो प्रोग्राम निष्पादित होने से पहले किसी अन्य तरीके से मेमोरी आवंटित करेगा। यह कोड लक्ष्य प्लेटफ़ॉर्म और OS के अनुसार अलग-अलग होगा। व्यवहार में, आधुनिक संकलक यह निर्धारित करने के लिए कि इनमें से किस विकल्प का उपयोग करने के लिए heuristics का उपयोग करते हैं। आप एक छोटा सी प्रोग्राम लिखकर इसे स्वयं आज़मा सकते हैं जो 10k, 1m, 10m, 100m, 1G या 10G आइटमों के बड़े स्थिर सरणी को आवंटित करता है। कई संकलक के लिए, द्विआधारी आकार सरणी के आकार के साथ रैखिक रूप से बढ़ता रहेगा, और एक निश्चित बिंदु से अतीत होगा,

मेमोरी रजिस्टर करें

अंतिम मेमोरी क्लास 'रजिस्टर' चर हैं। जैसा कि अपेक्षित था, रजिस्टर चर को सीपीयू के रजिस्टर पर आवंटित किया जाना चाहिए, लेकिन निर्णय वास्तव में संकलक के लिए छोड़ दिया गया है। आप पता-का उपयोग करके एक संदर्भ में एक रजिस्टर चर नहीं बदल सकते हैं।

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

अधिकांश आधुनिक संकलक आपसे बेहतर हैं कि कौन से चर को रजिस्टर में रखा जाना चाहिए :)

संदर्भ:


3
नोट: मैं int * a = malloc(sizeof(*a));इसके बजाय सुझाव देना चाहूंगा कि किस प्रकार के दोहराव से बचें a। यह चीजों को बहुत आसान बना देता है यदि कभी aपरिवर्तन के प्रकार ।
शाहबाज

1
अकस्मात इसे हीप कहा जाता है लेकिन इसका ढेर डेटा संरचना से कोई लेना-देना नहीं है। इस मामले में ढेर का मतलब है एक गन्दा स्थान
गतिशील

2
"स्थिर मेमोरी आवंटन ... संकलन समय पर आवंटित किया गया है" क्या आपका मतलब है कि आवंटन समय पर आवंटन आकार निर्धारित किया गया है? स्मृति के एक तरफ सेटिंग केवल रनटाइम पर ही नहीं होगी?
lf215

2

स्टैटिक मेमोरी एलोकेशन: कंपाइलर एक घोषित चर के लिए आवश्यक मेमोरी स्पेस आवंटित करता है। ऑपरेटर के पते का उपयोग करके, आरक्षित पता प्राप्त किया जाता है और यह पता एक पॉइंटर चर को सौंपा जा सकता है। तब घोषित किए गए अधिकांश वेरिएबल में स्थिर मेमोरी होती है, यह पॉइंटर वैरिएबल को पॉइंटर मान असाइन करने का तरीका स्टैटिक मेमोरी एलोकेशन के रूप में जाना जाता है। संकलन समय के दौरान स्मृति को सौंपा गया है।

डायनेमिक मेमोरी एलोकेशन: यह मेमोरी को गतिशील रूप से प्राप्त करने के लिए मॉलॉक () या कॉलोक () जैसे फ़ंक्शंस का उपयोग करता है। यदि इन फ़ंक्शंस का उपयोग मेमोरी को गतिशील रूप से प्राप्त करने के लिए किया जाता है और इन फ़ंक्शंस द्वारा दिए गए मान पॉइंटर वैरिएबल को दिए जाते हैं, तो ऐसे असाइनमेंट्स को डायनामिक मेमोरी के लिए जाना जाता है। आबंटन समय के दौरान आवंटन।


2

स्थैतिक मेमोरी आवंटन:

  • चर स्थायी रूप से आवंटित किए जाते हैं
  • आवंटन कार्यक्रम के निष्पादन से पहले किया जाता है
  • यह स्थैतिक आवंटन को लागू करने के लिए स्टैक नामक डेटा संरचना का उपयोग करता है
  • कम सक्षम
  • नहीं है कोई स्मृति पुनर्प्रयोग

गतिशील मेमोरी आवंटन:

  • वेरिएबल्स केवल तभी आवंटित किए जाते हैं जब प्रोग्राम यूनिट सक्रिय हो जाती है
  • आवंटन कार्यक्रम के निष्पादन के दौरान किया जाता है
  • यह गतिशील आवंटन को लागू करने के लिए ढेर नामक डेटा संरचना का उपयोग करता है
  • अधिक कुशल
  • नहीं है स्मृति पुनर्प्रयोग । आवश्यकता न होने पर मेमोरी को मुक्त किया जा सकता है

1
"स्टेटिक मेमोरी आवंटन [...] यह स्थैतिक आवंटन को लागू करने के लिए स्टैक नामक डेटा संरचना का उपयोग करता है" नहीं , यह गलत और भ्रामक है। कृपया स्वचालित और स्थिर आवंटन के बीच अंतर के लिए मेरी पोस्ट देखें। स्टैटिक मेमोरी स्टैक का उपयोग कर सकती है । यह दृढ़ता से कार्यान्वयन पर निर्भर है, और एक ही कार्यान्वयन के लिए कई रणनीतियों का उपयोग किया जा सकता है। मुझे यकीन नहीं है कि आप "कम कुशल" से क्या मतलब है। @ ट्राई टून, आपने इस उत्तर के अर्थ को एक खराब संपादन के साथ बदल दिया।
brice

1

स्टेटिक मेमोरी एलोकेशन और डायनामिक मेमोरी एलोकेशन के बीच अंतर

कार्यक्रम के निष्पादन (संकलन के दौरान) शुरू होने से पहले मेमोरी आवंटित की जाती है।
कार्यक्रम के निष्पादन के दौरान मेमोरी आवंटित की जाती है।

निष्पादन के दौरान कोई मेमोरी आवंटन या डील्लोकेशन क्रिया नहीं की जाती है।
मेमोरी बाइंडिंग निष्पादन के दौरान स्थापित और नष्ट हो जाते हैं।

चर स्थायी रूप से आवंटित किए जाते हैं।
केवल तभी आवंटित किया जाता है जब प्रोग्राम यूनिट सक्रिय हो।

ढेर और ढेर का उपयोग कर लागू किया गया।
डेटा सेगमेंट का उपयोग करके कार्यान्वित किया गया।

चर तक पहुँचने के लिए पॉइंटर की आवश्यकता होती है।
डायनामिक रूप से आवंटित पॉइंटर्स की कोई आवश्यकता नहीं है।

गतिशील की तुलना में तेज़ निष्पादन।
स्थिर की तुलना में धीमी निष्पादन।

अधिक मेमोरी स्पेस की आवश्यकता है।
कम मेमोरी स्थान की आवश्यकता।


1
स्थिर मेमोरी आवंटन को स्टैक पर आवंटित किया जाता है जबकि डायनेमिक मेमोरी आवंटन को हीप पर आवंटित किया जाता है
उस्मान कुर्द

@UsmanKurd यह आमतौर पर स्थिर मेमोरी के बारे में गलत है। मेरा जवाब देखिए।
ब्राईस

0

संकलन समय के दौरान निष्पादन पीएफ कार्यक्रम से पहले स्टैटिक मेमोरी आवंटन को मेमोरी आवंटित की जाती है। रन टाइम के दौरान प्रोग्राम के निष्पादन के दौरान डायनामिक मेमोरी एलोकेशन को अलोकेटेड मेमोरी कहा जाता है।


-1

स्थैतिक स्मृति आवंटन। आवंटित की गई मेमोरी स्टैक में होगी।

int a[10];

गतिशील स्मृति आवंटन। आवंटित स्मृति ढेर में होगी।

int *a = malloc(sizeof(int) * 10);

और उत्तरार्द्ध डी में कोई कचरा कलेक्टर (जीसी) नहीं होने के बाद से मुक्त होना चाहिए ।

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