2015-09-20 15 views
5

मैं स्ट्रॉस्ट्रप की सी ++ पीएल 4 पुस्तक अभ्यास अभ्यास करने की कोशिश कर रहा हूं। कार्य है:फ़ंक्शन bad_alloc अपवाद नहीं फेंकता

new का उपयोग करके इतनी मेमोरी आवंटित करें कि bad_alloc फेंक दिया गया है। रिपोर्ट करें कि कितनी मेमोरी आवंटित की गई थी और कितना समय लगा। इसे दो बार करें: एक बार आवंटित स्मृति को नहीं लिख रहा है और एक बार प्रत्येक तत्व को लिख रहा है।

निम्नलिखित कोड std::bad_alloc अपवाद नहीं फेंकता है। कार्यक्रम को निष्पादित करने के बाद मुझे टर्मिनल में "मार" संदेश मिलता है।

भी। निम्नलिखित कोड ~ 4 सेकंड में निकलता है। लेकिन जब मैं स्मृति उपयोग संदेश को अनमोल करता हूं

// ++i; 
// std::cout << "Allocated " << i*80 << " MB so far\n"; 

प्रोग्राम कुछ मिनटों तक चलाएगा। कुछ समय बाद यह प्रिंट करता है कि स्मृति के टेराबाइट आवंटित किए गए हैं लेकिन मुझे सिस्टम मॉनिटर ऐप में ज्यादा बदलाव नहीं दिख रहा है। ऐसा क्यों है?

मैं उपयोग देखने के लिए लिनक्स और सिस्टम मॉनिटर ऐप का उपयोग करता हूं।

#include <iostream> 
#include <vector> 
#include <chrono> 

void f() 
{ 
    std::vector<int*> vpi {}; 
    int i {}; 
    try{ 
     for(;;){ 
      int* pi = new int[10000]; 
      vpi.push_back(pi); 
      // ++i; 
      // std::cout << "Allocated " << i*80 << " MB so far\n"; 
     }  
    } 
    catch(std::bad_alloc){ 
     std::cerr << "Memory exhausted\n"; 
    } 
} 

int main() { 
    auto t0 = std::chrono::high_resolution_clock::now(); 
    f(); 
    auto t1 = std::chrono::high_resolution_clock::now(); 
    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t0-t1).count() << " ms\n"; 
} 
+0

आउटपुट एक साधारण स्मृति आवंटन से * अधिक * अधिक समय लेगा। यदि यह 2 मिनट तक चलता है, तो यह आउटपुट के लिए 1:56 हो सकता है और आवंटन के लिए अभी भी 4 सेकंड हो सकता है। –

+0

वह मेरा अंतर्ज्ञान था। लेकिन यह क्यों प्रिंट करता है, मान लें, स्मृति के टेराबाइट अब तक आवंटित किए गए थे? – tomtom

+0

संभावित डुप्लिकेट [प्रक्रिया के "असली" मेमोरी उपयोग, यानी निजी गंदे आरएसएस को निर्धारित करने का एक तरीका?] (Http://stackoverflow.com/questions/118307/a-way-to-determine-a-processs-real- मेमोरी-यूज-यानी-प्राइवेट-गंदे-आरएसएस) –

उत्तर

5

आधुनिक क्रूर दुनिया new बुला में (और साथ ही malloc() या यहाँ तक कि brk()) जरूरी स्मृति को आबंटित नहीं है। यह सिर्फ एक ओएस के अनुरोध (परतों की एक श्रृंखला के माध्यम से) भेजता है और ओएस वर्चुअल स्मृति क्षेत्र (सिस्टम मेमोरी पृष्ठों के लिए गोलाकार) असाइन करता है। तो बाद में किसी दिए गए मेमोरी में तक पहुंचने से वास्तविक आवंटन होता है।

इसके अलावा आधुनिक ओएस मेमोरी "ओवरकमिट" की अनुमति देते हैं। कभी-कभी (ओएस और इसकी सेटिंग्स के आधार पर) अनुप्रयोग पूरी तरह से अधिक स्मृति मांग सकते हैं कि ओएस सैद्धांतिक रूप से असाइन कर सकता है, जिसमें इसके सभी स्वैप क्षेत्रों आदि शामिल हैं, सभी w/o किसी भी दृश्य समस्या। उदाहरण के लिए at this page देखें।

ऐसा इसलिए किया जाता है क्योंकि वास्तविक जीवन में एक स्थिति जब सभी अनुप्रयोग वास्तव में में सभी आवंटित स्मृति का उपयोग करेंगे, उसी समय काफी असंभव है। अधिकतर, 99.99 .. समय का%, एप्लिकेशन केवल अपनी याददाश्त के कुछ हिस्सों का उपयोग करते हैं और इसे क्रमशः करते हैं, इसलिए एक ओएस को अपने अनुरोधों को निर्बाध रूप से सेवा करने का मौका मिलता है।

को वास्तव में स्मृति आवंटन त्रुटि का कारण बनने की संभावना बढ़ जाती है, तो आप केवल आवंटित तत्व तक पहुंच सकते हैं, लेकिन फिर मैं इसे "संभावनाओं को बढ़ाने के बारे में" एक क्रियात्मक वारंटी नहीं कहूंगा।

सबसे खराब स्थिति में जब ऐसा ओएस वास्तव में पाया जाता है कि यह पर्याप्त (वर्चुअल) मेमोरी असाइन नहीं कर सकता है क्योंकि बहुत से ऐप्स ने अपने सीमांकित आवंटित डेटा तक पहुंच का अनुरोध किया है, ओएस मेमोरी मैनेजर ने "ओओएम किलर" नामक एक विशेष प्रक्रिया शुरू की है। जो आसानी से heuristically (= यादृच्छिक रूप से :)) चुने गए अनुप्रयोगों को मारता है।

तो bad_alloc पर भरोसा करना आजकल एक बुरा विचार है। कभी-कभी आप इसे वास्तविक रूप से प्राप्त कर सकते हैं (उदाहरण के लिए जब कृत्रिम रूप से ulimit/setrlimit के साथ कृत्रिम रूप से सीमित हो), लेकिन आम तौर पर आपका आवेदन ऐसे माहौल में चलाएगा जो कुछ भी गारंटी नहीं देगा। बस एक स्मृति हॉग न हो और बाकी के लिए प्रार्थना करें :)

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