2010-07-24 17 views
8

शायद हर किसी के विकास के दौरान कम से कम एक बार इस समस्या का सामना किया:विकास के दौरान "मौत की स्वैपिंग" से कैसे बचें?

while(/*some condition here that somehow never will be false*/) 
{ 
    ... 
    yourvector.push_back(new SomeType()); 
    ... 
} 

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

आप नीचे बग को ट्रैक नहीं कर सकते तो आप तुरंत कई परीक्षण की आवश्यकता होगी और पता लगाने के लिए जो बहुत कष्टप्रद है रीसेट करता है ...

मैं एक संभवतः पार मंच तरीका इसे रोकने के लिए की तलाश में हूँ किसी न किसी तरह। सबसे अच्छा एक डीबग मोड कोड होगा जो प्रोग्राम से बाहर निकलता है अगर यह बहुत अधिक स्मृति आवंटित करता है, लेकिन मैं कैसे ट्रैक कर सकता हूं कि कितनी मेमोरी आवंटित की जाती है? वैश्विक नए ओवरराइडिंग और ऑपरेटरों को हटाने में मदद नहीं मिलेगी, क्योंकि हटाए गए नि: शुल्क फ़ंक्शन में मैं कोई विचार नहीं दूंगा कि कितने बाइट मुक्त हैं।

किसी भी विचार की सराहना की।

+1

किस ऑपरेटिंग सिस्टम का उपयोग कर रहे हैं? कितनी रैम? पेजिंग फ़ाइल का आकार क्या है? जानना जरूरी है। –

+0

आप त्रुटि की इस तरह से ग्रस्त हैं, तो बस स्वैप बंद कर देते हैं। मुझे एक महीने से ऊपर की अपटाइम के साथ मेरे सामने भारी उपयोग की जाने वाली विकास मशीन मिली है। इस्तेमाल किए गए अधिकतम स्वैप के लिए उच्च-पानी का निशान 22 एमआईबी है। (Linux 2.6.32 4GiB कोर, swapiness 60) – msw

उत्तर

10

वैश्विक नए ओवरराइडिंग और ऑपरेटरों को हटाने में मदद नहीं मिलेगी, क्योंकि हटाए गए नि: शुल्क फ़ंक्शन में मुझे कोई विचार नहीं होगा कि कितने बाइट मुक्त हैं।

लेकिन आप इसे ऐसा कर सकते हैं।

namespace 
{ 
    // utility 
    std::new_handler get_new_handler(void) 
    { 
     std::new_handler handler = std::set_new_handler(0); 
     std::set_new_handler(handler); 

     return handler; 
    } 

    // custom allocation scheme goes here! 
    void* allocate(std::size_t pAmount) 
    { 

    } 

    void deallocate(void* pMemory) 
    { 

    } 

    // allocate with throw, properly 
    void* allocate_throw(std::size_t pAmount) 
    { 
     void* result = allocate(pAmount); 

     while (!result) 
     { 
      // call failure handler 
      std::new_handler handler = get_new_handler(); 
      if (!handler) 
      { 
       throw std::bad_alloc(); 
      } 

      handler(); 

      // try again 
      result = allocate(pAmount); 
     } 

     return result; 
    } 
} 

void* operator new(std::size_t pAmount) throw(std::bad_alloc) 
{ 
    return allocate_throw(pAmount); 
} 

void *operator new[](std::size_t pAmount) throw(std::bad_alloc) 
{ 
    return allocate_throw(pAmount); 
} 

void *operator new(std::size_t pAmount, const std::nothrow_t&) throw() 
{ 
    return allocate(pAmount); 
} 

void *operator new[](std::size_t pAmount, const std::nothrow_t&) throw() 
{ 
    return allocate(pAmount); 
} 

void operator delete(void* pMemory) throw() 
{ 
    deallocate(pMemory); 
} 

void operator delete[](void* pMemory) throw() 
{ 
    deallocate(pMemory); 
} 

void operator delete(void* pMemory, const std::nothrow_t&) throw() 
{ 
    deallocate(pMemory); 
} 

void operator delete[](void* pMemory, const std::nothrow_t&) throw() 
{ 
    deallocate(pMemory); 
} 

तो फिर तुम जैसे कुछ कर सकते हैं:: यहाँ वैश्विक स्मृति ऑपरेटरों अधिक भार (कुछ global_memory.cpp फ़ाइल में फेंक) के लिए एक पूर्ण ढांचा है

// custom allocation scheme goes here! 
    const std::size_t allocation_limit = 1073741824; // 1G 
    std::size_t totalAllocation = 0; 

    void* allocate(std::size_t pAmount) 
    { 
     // make sure we're within bounds 
     assert(totalAllocation + pAmount < allocation_limit); 

     // over allocate to store size 
     void* mem = std::malloc(pAmount + sizeof(std::size_t)); 
     if (!mem) 
      return 0; 

     // track amount, return remainder 
     totalAllocation += pAmount; 
     *static_cast<std::size_t*>(mem) = pAmount; 

     return static_cast<char*>(mem) + sizeof(std::size_t); 
    } 

    void deallocate(void* pMemory) 
    { 
     // get original block 
     void* mem = static_cast<char*>(pMemory) - sizeof(std::size_t); 

     // track amount 
     std::size_t amount = *static_cast<std::size_t*>(mem); 
     totalAllocation -= pAmount; 

     // free 
     std::free(mem); 
    } 
+0

आबंटित स्थान पर आकार भंडारण एक अच्छा विचार है। यह मेरे दिमाग में क्यों नहीं आया ... यह भी इंगित करने के लिए +1 है कि मुझे नए के फेंकने और गैर-फेंकने वाले संस्करणों को ओवरराइड करना चाहिए और हटाएं, मैं उन्हें पूरी तरह से भूल गया। :) – Calmarius

1

क्योंकि मुक्त समारोह मैं हटाने में आह्वान हैं किसी भी विचार कितने बाइट्स मुक्त कर दिया जाता है

यह कर सकते हैं नहीं देंगे, तो आप सिर्फ आकार का एक नक्शा रखने के लिए आवंटित की है पते के आधार पर स्मृति, और उस जानकारी के आधार पर सही राशि को घटाएं।

+0

एसटीएल नक्शा वैश्विक नए का उपयोग करें और भी हटाना जब तक आप उसे अपनी खुद की संभाजक देना होगा कि वैश्विक एक से स्वतंत्र। मुझे एक अनंत रिकर्सन की संभावना दिखाई देती है। – Calmarius

0

आप को लागू कर सकता है आप वैश्विक नए ऑपरेटर के मालिक हैं:

void* operator new (std::size_t size) throw (std::bad_alloc); 
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw(); 
void* operator new (std::size_t size, void* ptr) throw(); 

void* operator new[] (std::size_t size) throw (std::bad_alloc); 
void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_constant) throw(); 
void* operator new[] (std::size_t size, void* ptr) throw(); 

फिर, बस आप कितना स्मृति को आबंटित के बारे में एक कठिन सीमा निर्धारित; हो सकता है कि कैसे moch Kb/sec

13

यदि आप लिनक्स या यूनिक्स-आईएसएच सिस्टम पर हैं, तो आप setrlimit(2) पर जांच सकते हैं जो आपको अपने प्रोग्राम के लिए संसाधन सीमा कॉन्फ़िगर करने की अनुमति देता है। आप शेल से ulimit के साथ समान चीजें कर सकते हैं।

+0

+1 क्योंकि यह एक और चीज है जिसे मैं नहीं जानता था। लेकिन मैं अपने कार्यक्रम क्रॉस प्लेटफॉर्म होना चाहते हैं, तो कभी कभी मैं लिनक्स के तहत कभी कभी Windows के तहत इसे विकसित और मेरी समस्या दोनों पक्षों पर हो सकता है। – Calmarius

0

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

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