2013-05-28 28 views
8

निम्नलिखित सी कोड है, जो 100,000 4KB आकार पृष्ठों बनाता है पर विचार करें, तो 99,999 पृष्ठों को मुक्त कर देते हैं और, अंत में, अंतिम पृष्ठ को मुक्त कर देते:मेमोरी रिसाव

#include <stdio.h> 
#include <stdlib.h> 

#define NUM_PAGES 100000 

int main() { 
    void *pages[NUM_PAGES]; 

    int i; 
    for(i=0; i<NUM_PAGES; i++) { 
     pages[i] = malloc(4096); 
    } 

    printf("%d pages allocated.\n", NUM_PAGES); 
    getchar(); 

    for(i=0; i<NUM_PAGES-1; i++) { 
     free(pages[i]); 
    } 

    printf("%d pages freed.\n", NUM_PAGES-1); 
    getchar(); 

    free(pages[NUM_PAGES-1]); 

    printf("Last page freed.\n"); 
    getchar(); 

    return 0; 
} 

आप इसे संकलन हैं, चलाने यह और इस प्रक्रिया 'स्मृति उपयोग पर नजर रखने के लिए, आप देख सकते हैं कि स्मृति के उपयोग पहले getchar (के बाद (जब स्मृति 100,000 पृष्ठों के लिए आवंटित किया जाता है), तो यह एक ही के बाद भी 99,999 पृष्ठों को डी-आवंटित किए जाते हैं रहता है दूसरे से पहले 400MB के बारे में पहुंचता है getchar) और, आखिरकार, यह अंतिम पृष्ठ को आवंटित होने पर 1 एमबी तक गिर जाता है।

तो, मेरे सवाल क्यों हो रहा है है? पूरी याददाश्त ओएस में क्यों लौटी जाती है जब सभी पेज मुक्त हो जाते हैं? क्या कोई पृष्ठ आकार या कोई पृष्ठ संरेखण है जो इस तरह की चीज को होने से रोकता है? मेरा मतलब है, क्या कोई पृष्ठ आकार या संरेखण है जो किसी भी मॉलोकर्ड पेज को पूरी तरह से ऑपरेटिंग सिस्टम पर वापस कर देता है जब केवल एक पृष्ठ मुक्त हो जाता है?

+3

ऐसा इसलिए होता है क्योंकि आवंटन इतने छोटे होते हैं कि आपकी सी लाइब्रेरी अपने अनियंत्रित डेटा को गतिशील रूप से आकार देने के लिए 'sbrk()' का उपयोग करती है। यह अनुक्रमिक है, इसलिए जब नवीनतम आवंटन मुक्त हो जाता है तो यह केवल तंग हो सकता है। यदि आप 131072 बाइट्स (128 के) कहने के लिए आवंटन आकार बढ़ाते हैं, तो 'स्ट्रेस' से पता चलता है कि यह आवंटन के लिए 'mmap()' का उपयोग करता है, और प्रत्येक 'मुक्त()' वास्तव में ओएस को आवंटन देता है। तो, आवंटन कैश का उपयोग करें, और केवल ओएस को बड़े भाग पूछें/वापस करें। –

+0

@ नाममात्र अंतिम आदमी, आपने मेरी जान बचाई! ऊपर और नीचे टिप्पणियों के लिए बहुत बहुत धन्यवाद। यही वही है जो मैं जवाब से उम्मीद कर रहा था। यदि आपने इसका जवाब दिया था (टिप्पणी नहीं की थी), तो मैंने आपका जवाब स्वीकार कर लिया होगा ... – LuisABOL

उत्तर

5

यह पूरी तरह से कार्यान्वयन पर निर्भर है, लेकिन मेरा मानना ​​है कि यह कैसे काम करता है स्मृति allocator से कोई लेना देना नहीं है। आमतौर पर, जब स्मृति प्रबंधक को ओएस से अधिक मेमोरी की आवश्यकता होती है, तो यह अतिरिक्त मेमोरी का अनुरोध करने के लिए sbrk फ़ंक्शन को कॉल करता है। इस फ़ंक्शन का सामान्य कार्यान्वयन यह है कि ओएस स्मृति में अगले निशुल्क पते पर एक पॉइंटर संग्रहीत करता है जहां प्रक्रिया स्थान प्राप्त कर सकती है। स्मृति एक ढेर की तरह बढ़ती है, वैसे ही कॉल स्टैक काम करता है। उदाहरण के लिए, यदि आप स्मृति के पांच पृष्ठों आवंटित, यह इस प्रकार दिखाई देंगे: इस स्थापना के साथ

(existing memory) | Page 0 | Page 1 | Page 2 | Page 3 | Page 4 | (next free spot) 

, अगर आप नि: शुल्क पृष्ठ 0 - 4, कार्यक्रम के अंदर स्मृति प्रबंधक उन्हें मुक्त इस तरह का प्रतीक होगा, :

(existing memory) |         | Page 4 | (next free spot) 

के बाद से ओएस एक ढेर की तरह फैशन में स्मृति का आवंटन किया जाता है, यह कार्यक्रम से यह सब स्मृति को पुनः प्राप्त नहीं कर सकते जब तक पेज 4 इस्तेमाल किया जा रहा किया जाता है। तुम बहुत अंतिम पृष्ठ मुक्त एक बार, इस प्रक्रिया की स्मृति इस तरह दिखेगा:

(existing memory) |            (next free spot) 

और इस बिंदु पर कार्यक्रम की स्मृति प्रबंधक ओएस के लिए मुक्त अंतरिक्ष के कि भारी मात्रा में लौट सकते हैं:

(existing memory) | (next free spot) 

दूसरे शब्दों में, क्योंकि स्मृति को स्टैक के रूप में आवंटित किया जाता है, जब तक कि आप आवंटित की गई आखिरी चीज़ को हटा नहीं देते हैं, ओएस किसी भी स्मृति को पुनः प्राप्त नहीं कर सकता है।

आशा है कि इससे मदद मिलती है!

+0

ठीक है, उत्तर देने के लिए बहुत बहुत धन्यवाद! स्मृति आवंटन के बारे में बहुत अच्छी व्याख्या। लेकिन, मैं जानना चाहता हूं कि क्या आप स्टैक-जैसी स्मृति आवंटन से बचने के लिए किसी भी तरह से जानते हैं, मेरा मतलब है, व्यक्तिगत पृष्ठों का आवंटन जो अलग-अलग हटाए जाते हैं। – LuisABOL

+2

@ लुइसएन्टोनियोबोटेल्हो.लाइट आपको ओएस से सीधे स्मृति प्राप्त करने/रिलीज करने के लिए ओएस-निर्भर कॉल की आवश्यकता होगी। विंडोज़ के तहत आप [वर्चुअलअलोक] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887 (v ​​= vs.85) .aspx) और [वर्चुअलफ्री] (http: // msdn) का उपयोग करते हैं। माइक्रोसॉफ्ट।com/en-us/पुस्तकालय/विंडोज़/डेस्कटॉप/aa366892 (v = vs.85) .aspx)। यूनिट पर, [sbrk (2)] (http://linux.die.net/man/2/sbrk) का उपयोग करें। ध्यान दें कि आपको केवल मॉलोक/फ्री का उपयोग करने और एसआरबीके से बचने के लिए चेतावनी दी जाती है। – Anthony

+0

@ एंथनी-अर्नोल्ड बहुत बहुत धन्यवाद! – LuisABOL

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