2015-11-29 5 views
5

मैं सी के साथ प्रयोग करना जारी रखता हूं। मेरे पास यह प्रोग्राम है जो आपको यह तय करने की अनुमति देता है कि आप कितनी रैम खाना चाहते हैं।सी के साथ प्रयोग - मैं 2 जीबी मेमोरी आवंटित और उपयोग क्यों नहीं कर सकता?

char * eatRAM() 
{ 
    unsigned long long toEat; 
    unsigned long long i = 0; 
    float input; 
    char * pMemory = NULL; 
    int megaByte = 1048576; 

    puts("How much RAM do you want to eat? (in Mega Bytes)"); 
    puts("NOTE: If you want to eat more RAM than you have available\nin your system, the program will crash"); 
    printf("\n>> MB: "); 
    scanf("%f", &input); 

    toEat = (unsigned long long)(input * megaByte); 
    pMemory = malloc(toEat); 

    printf("\n\nEating in total: %llu Bytes\n", toEat); 
    puts("Check your task manager!\n"); 

    if(pMemory != NULL) 
    { 
     printf("\n\nEating in total: %llu Bytes\n", toEat); 
     puts("Check your task manager!\n"); 

     for(i; i < toEat; i++) 
     { 
      pMemory[i] = 'x'; 
     } 
    } 
    else 
    { 
     puts("\nSeems like that amount of memory couldn't be allocated :(\n"); 
    } 
    return pMemory; 
} 

UPDATED प्रश्न:

बात यह है कि ... अगर मैं उदाहरण 1024MB यह काम करता है के लिए दर्ज करते हैं, मैं कार्य प्रबंधक में देख सकते हैं यह राम के 1GB उपयोग कर रहा है। यहां तक ​​कि अगर मैं 1500MB यह काम करता है ..

दर्ज लेकिन अगर मैं 2048MB दर्ज यह कहता है

स्मृति के उस राशि आवंटित नहीं किया जा सका :(

या की तरह लगता है भले ही मैं 1756MB

याद रखें कि मैं सी के लिए नया हूं, शायद मैं कुछ महत्वपूर्ण रिलाट छोड़ रहा हूं ओएस कैसे मुझे स्मृति तक पहुंचने की अनुमति देता है, यह क्या हो सकता है?

+0

malloc शायद विफल हो जाता है और शून्य लौटाता है, तो –

+0

क्रैश की जांच करें क्योंकि आप स्मृति तक पहुंचने का प्रयास करते हैं हालांकि आवंटन विफल हुआ, आपको इसका उपयोग करने से पहले 'pmemory! = NULL' को जांचना होगा। साथ ही, आपको 'malloc() 'नहीं डालना चाहिए, सामान्य रूप से कभी भी' शून्य * 'से किसी अन्य सूचक को नहीं डाला जाना चाहिए। –

+0

आपके कंप्यूटर में कितनी रैम है? –

उत्तर

5

विंडोज़ पर 32-बिट प्रक्रिया में डिफ़ॉल्ट रूप से 2 गिगाबाइट पता स्थान उपलब्ध है। पूर्ण पाउ (2, 32) पता स्थान का निचला आधा, ऑपरेटिंग सिस्टम द्वारा शीर्ष 2 जीबी का उपयोग किया जाता है। चूंकि कोई भी 32-बिट ओएस का उपयोग नहीं करता है, इसलिए जब आप अपने प्रोग्राम को/LARGEADDRESSAWARE से लिंक करते हैं तो आप 4 जीबी प्राप्त कर सकते हैं।

उस 2 जीबी वीएम स्पेस को कोड और डेटा द्वारा साझा करने की आवश्यकता है। आपका प्रोग्राम आमतौर पर 0x00400000 पर लोड होता है, आपके द्वारा उपयोग किए जाने वाले किसी भी ऑपरेटिंग सिस्टम DLL (जैसे kernel32.dll और ntdll.dll) में उच्च लोड पते होते हैं (0x7F000000 से परे)। और कम से कम स्टार्टअप थ्रेड का ढेर और डिफ़ॉल्ट प्रोग्राम ढेर आपके प्रोग्राम को चलने से पहले बनाया जाता है, उनके पते आमतौर पर अप्रत्याशित होते हैं।

आपके प्रोग्राम को किसी भी ओएस इंस्टॉल में सिकुंक-लिपटे वायरल हमलों के अधीन किया जाएगा, आपके पास डीएलएल इंजेक्शन होगा जो एंटी-मैलवेयर और क्लाउड स्टोरेज जैसी "सेवाएं" प्रदान करेगा। उन डीएलएल का भार पता अप्रत्याशित है। आपके साथ जुड़े किसी भी डीएलएल और आपके प्रोग्राम शुरू होने पर पूरी तरह से लोड हो जाते हैं। कुछ प्रोग्रामर अपने पसंदीदा आधार पते पर ध्यान देते हैं और इसे डिफ़ॉल्ट, 0x1000000 पर छोड़ देते हैं। आप इन डीएलएल को डीबगर की मॉड्यूल विंडो से देख सकते हैं। ऐसे डीएलएल में अक्सर अपना स्वयं का सीआरटी होता है और वे अपने ही ढेर बनाने के लिए जाते हैं।

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

ये विवरण तेजी से लोक कथा बन रहे हैं, अभी भी x86 को लक्षित करने के बहुत कम शेष कारण हैं। लक्ष्य x64 और पता स्थान विखंडन अगले 20 वर्षों के लिए एक समस्या नहीं होगी, वीएम के 8 टेराबाइट टुकड़े करने के लिए बहुत मुश्किल है। इसके अलावा बढ़ने के लिए बहुत सारे हेडरूम के साथ।

तो यह स्पष्ट होना चाहिए कि आपको 2048 एमबी क्यों नहीं मिल सकता है, आप इसे सब कुछ नहीं प्राप्त कर सकते हैं। SysInternals 'VMMap utility से और अंतर्दृष्टि प्राप्त करें, यह आपको दिखाता है कि वीएम कैसे बना है। और मार्क रसेलिनोविच 'blog post और पुस्तक बहुत सारी पृष्ठभूमि देती है।

+0

इस तरह के एक अच्छी तरह से समर्थित उत्तर देने के लिए समय लेने के लिए धन्यवाद! शोध और अभ्यास पर बने रहेंगे! - चीयर्स! –

0

आवंटन कभी भी काम नहीं करेगा यदि शेष खाली मेमोरी की राशि आवंटित करने की कोशिश कर रहे राशि से कम है।

इसके अलावा, सही इस लाइन के बाद:

pMemory = (char *) malloc(toEat); 

निम्नलिखित जोड़ें: बदले "विभाजन गलती" संबंधित संदेशों को प्राप्त करने,

if (!pMemory){ 
    printf("Can't allocate memory\n"); 
    return NULL; 
} 

इस तरह, आप देखेंगे एक "कैन ' टी स्मृति आवंटित करें "इसके बजाय संदेश और आपका फ़ंक्शन न्यूल लौटाएगा।

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

+1

पर अलग नहीं होगी जवाब देने के लिए माइक धन्यवाद। वास्तव में 2048 एमबी के साथ परीक्षण चलाने के समय मेरे पास 5 जीबी से अधिक उपलब्ध रैम है, आपको क्या लगता है? इसके अलावा, मैंने कुछ मिनट पहले अपने कोड को अपडेट किया था, इसलिए यह मैलोक की वापसी को ठीक से संभाला। एक बार फिर धन्यवाद! –

+2

@ जुआनबोननेट कृपया ध्यान दें कि 'मॉलोक' का उपयोग करने का मतलब है कि आप जिस मेमोरी का उपयोग कर रहे हैं वह कोड का एक विशाल ब्लॉक है, भले ही आपके पास 2-3 + जीबी की मुफ्त मेमोरी हो, हो सकता है कि इसमें 1 जीबी फ्री ब्लॉक न हो। साथ ही मुझे लगता है कि मैंने कहीं पढ़ा है कि इस कारण से, विंडोज़ में कुछ "ब्लॉक सीमाएं" हैं, इसलिए एप्लिकेशन अन्य ऐप्स या उस तरह से कुछ स्मृति से आवंटित करने का प्रयास नहीं करेंगे। – TomTsagk

3

यह एक सी सीमा के बजाय एक ओएस सीमा है।

4Gb प्रणाली की तुलना में अधिक पता करने के लिए विस्तृत आप एक 64 बिट OS चलाने की जरूरत है और के लिए एक एकल प्रक्रिया 4GB से अधिक पता करने के लिए यह एक 64 बिट अनुप्रयोग के रूप में बनाया जाना चाहिए। Win32 प्रति प्रोसेस मेमोरी सीमा 2 जीबी है। मेमोरी वर्चुअलाइज्ड होने के बाद से 5 जीबी भौतिक रैम काफी हद तक अप्रासंगिक है।

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

अपने मामले में एक विशिष्ट जवाब आपके सिस्टम, toolchain के बारे में जानकारी की आवश्यकता होती है और लागू विकल्पों का निर्माण होगा। यदि आप विंडोज और वीसी ++ का उपयोग कर रहे हैं तो आपको /LARGEADDRESAWARE विकल्प पर विचार करने की आवश्यकता है; यह 32 बिट कंपाइलर में डिफ़ॉल्ट रूप से सक्षम नहीं है, लेकिन Win32 में किसी भी मामले में 2 जीबी डिफ़ॉल्ट सीमा है जब तक कि physical address extension सक्षम नहीं है।

मेरा मानना ​​है कि Win64 पर चल रही 32 बिट प्रक्रिया पूर्ण 4 जीबी 32 बिट एड्रेस स्पेस को संबोधित कर सकती है, लेकिन आपको निश्चित रूप से उस मामले में /LARGEADDRESAWARE के साथ निर्माण करने की आवश्यकता होगी।फिर भी वह जगह ढेर के लिए पर्याप्त नहीं होगी, और कोई भी आवंटन संगत होना चाहिए, इसलिए पिछले आवंटन और ढेर विखंडन द्वारा सीमित किया जा सकता है।

+0

इस तरह के एक अच्छी तरह से समर्थित उत्तर देने के लिए समय लेने के लिए धन्यवाद! शोध और अभ्यास पर बने रहेंगे! - चीयर्स! –

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