c++ - रखरख - विद्यालय पुस्तकालय के नियम




तीसरे पक्ष के पुस्तकालय कोड में मेमोरी आवंटन रणनीति को कैसे नियंत्रित किया जाए? (2)

उस वर्ग के पुस्तकालय के भीतर किए गए आवंटन के लिए केंट नहीं लगाया जा सकता है, लेकिन आप उस तृतीय पक्ष लाइब्रेरी से कक्षाएं आवंटित करने के लिए प्लेसमेंट नए का उपयोग कर सकते हैं अर्थात आप मेमोरी आवंटित कर सकते हैं और उन कक्षाओं के कंस्ट्रक्टर को आवंटित मेमोरी पर बुलाया जा सकता है। इस तरह से भले ही कक्षा हो अपने स्वयं के नए ऑपरेटर को यह नहीं कहा जाता है। घर का काम करने वाले वर्ग के अंदर, अनपेक्षित आंतरिक वर्गों या आदिम वर्ग के मेमोरी आवंटन के अंदर तीसरे पक्ष के पुस्तकालय की आवंटन योजना का उपयोग करके किया जाएगा; जब तक कि तृतीय पक्ष पुस्तकालय आपको stl कंटेनरों की तरह एक एलोकेटर निर्दिष्ट करने की अनुमति न दे, तब तक इसे नहीं बदला जा सकता

पिछला शीर्ष लेख: "क्या मुझे वैश्विक ऑपरेटरों को प्रतिस्थापित करना चाहिए और तृतीय पक्ष कोड में मेमोरी आवंटन रणनीति बदलने के लिए हटाना चाहिए?"

लघु कहानी: हमें अपने सोर्स कोड को बदले बिना मेमोरी एलोकेशन तकनीक को थर्ड-पार्टी लाइब्रेरी में बदलने की आवश्यकता है।

लम्बी कहानी:

स्मृति-बाध्य अनुप्रयोग पर विचार करें जो विशाल गतिशील आवंटन बनाता है (शायद, लगभग सभी उपलब्ध सिस्टम मेमोरी)। हम विशेष आबंटक का उपयोग करते हैं, और उन्हें हर जगह ( shared_ptr के कंटेनरों आदि) का उपयोग करते हैं। हमारे पास हमारे एप्लिकेशन में आवंटित हर एक बाइट पर कुल नियंत्रण और शक्ति है।

इसके अलावा, हमें तीसरे पक्ष के सहायक पुस्तकालय के खिलाफ लिंक करने की आवश्यकता है। वह बुरा आदमी कुछ मानक तरीके से आवंटन करता है, डिफ़ॉल्ट ऑपरेटरों का उपयोग करते हुए new , new[] , delete और delete[] या malloc या कुछ और गैर-मानक (चलो सामान्यीकरण करें और कहें कि हम नहीं जानते कि यह पुस्तकालय कैसे प्रबंधन करता है यह ढेर आवंटन है )।

यदि यह सहायक पुस्तकालय आवंटन करता है जो काफी बड़ा है तो हम एचडीडी थ्रैशिंग, मेमोरी विखंडन और संरेखण मुद्दे, आउट-ऑफ-मेमोरी bad_alloc एस और सभी प्रकार की समस्याओं को प्राप्त कर सकते हैं।

लाइब्रेरी सोर्स कोड को बदलने के लिए हम (या नहीं चाहते) कर सकते हैं।

पहली कोशिश:

रिलीज बिल्डअप से पहले हमारे पास ऐसी अपवित्र "हैक" कभी नहीं थी। ओवरराइडिंग ऑपरेटर new कार्यों के साथ पहला परीक्षण ठीक है, सिवाय इसके कि:

  • हम यह नहीं जानते कि भविष्य में कौन से गोटे हमारा इंतजार करते हैं (और यह भयानक है)
  • हमारे उपयोगकर्ताओं (और यहां तक ​​कि हमारे आवंटनकर्ता) को अब उसी तरह आवंटित करना होगा जो हम करते हैं

प्रशन:

  1. क्या वैश्विक ऑपरेटरों को ओवरलोड किए बिना इन आवंटन को हुक करने के तरीके हैं? (स्थानीय परिवाद-केवल हुक?)
  2. ... और अगर हम नहीं जानते कि यह वास्तव में क्या उपयोग करता है: malloc या new ?
  3. क्या हस्ताक्षर की यह सूची पूर्ण है? (और कोई अन्य चीजें नहीं हैं जिन्हें हमें लागू करना चाहिए):

    void* operator new (std::size_t size) throw (std::bad_alloc);
    void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) 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_value) throw();
    void* operator new[] (std::size_t size, void* ptr) throw();
    
    void operator delete (void* ptr) throw();
    void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) throw();
    void operator delete (void* ptr, void* voidptr2) throw();
    void operator delete[] (void* ptr) throw();
    void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw();
    void operator delete[] (void* ptr, void* voidptr2) throw();
  4. कुछ अलग है अगर वह पुस्तकालय गतिशील है?

# 1 संपादित करें

यदि संभव हो तो क्रॉस-प्लेटफ़ॉर्म समाधान बेहतर है (बहुत संभव नहीं लगता है)। यदि नहीं, तो हमारे प्रमुख प्लेटफार्म:

  • Windows x86 / x64 (msvc 10)
  • लिनक्स x86 / x64 (gcc 4.6)

# 2 संपादित करें

लगभग 2 साल बीत चुके हैं, कुछ ओएस और कंपाइलर संस्करण विकसित हुए हैं, इसलिए मैं उत्सुक हूं कि क्या इस क्षेत्र में कुछ नया और अस्पष्टीकृत है? कोई मानक प्रस्ताव? ओएस-बारीकियों? हैक्स? आज आप स्मृति-प्यास अनुप्रयोगों को कैसे लिखते हैं? कृपया अपना अनुभव साझा करें।


ऊ, मेरी सहानुभूति। यह आपके कंपाइलर, आपके libc इत्यादि पर बहुत कुछ निर्भर करने वाला है। कुछ रबर-मीट-रोड की रणनीतियां जिन्होंने अतीत में हमारे लिए अलग-अलग डिग्री के लिए "काम" किया है (/ डाउनवोट के लिए मुझे ब्रेसेस):

  • operator new / operator delete आपके द्वारा सुझाए गए ओवरलोड्स को operator delete - हालांकि ध्यान दें कि कुछ संकलक throw() चश्मा के बारे में नहीं हैं, कुछ वास्तव में उन्हें चाहते हैं, कुछ उन्हें नए के लिए चाहते हैं, लेकिन हटाने के लिए नहीं, आदि (मेरे पास एक विशाल मंच-विशिष्ट है #if / #elif उन सभी 4+ प्लेटफार्मों के लिए ब्लॉक करें, जिन पर हम अभी काम कर रहे हैं)।
  • इसके अलावा ध्यान देने योग्य: आप आमतौर पर प्लेसमेंट संस्करणों को अनदेखा कर सकते हैं, वे आवंटित नहीं करते हैं।
  • __malloc_hook और दोस्तों को देखें - ध्यान दें कि ये पदावनत हैं और थ्रेड रेस की स्थिति है - लेकिन वे उस नए / हटाए जाने की प्रवृत्ति में malloc संदर्भ में लागू होते हैं (लेकिन हमेशा नहीं)।
  • एक रिप्लेसमेंट calloc , calloc , calloc और free प्रदान करना और अपने लिंकर को सही क्रम में प्राप्त करना ताकि ओवरराइड्स हो जाएं (यह वही है जो इन दिनों की सिफारिश करता है, हालांकि मेरे पास ऐसी परिस्थितियां हैं जहां यह करना असंभव था, और मैं __malloc_hook गए __malloc_hook का उपयोग करना पड़ा) - फिर से, new और delete प्रवृत्ति को इन के संदर्भ में लागू किया जाना चाहिए, लेकिन हमेशा नहीं।
  • "हमारे कोड" में सभी मानक आवंटन विधियों ( operator new , malloc , आदि) से बचना और इसके बजाय कस्टम फ़ंक्शन का उपयोग करना - मौजूदा कोडबेस के साथ बहुत आसान नहीं है।
  • लाइब्रेरी लेखक को ट्रैक करना और एक अलग आवंटन आवंटित करने की अनुमति देने के लिए उनके पुस्तकालय को बदलने के लिए एक विनम्र पिटाई विनम्र अनुरोध या पैच वितरित करना (यह अपने आप ऐसा करने से तेज हो सकता है) - मुझे लगता है कि इससे "ग्राहक" का कार्डिनल नियम हो सकता है हमेशा आवंटनकर्ता को निर्दिष्ट करता है या आवंटन करता है "मेरे द्वारा लिखे गए किसी भी पुस्तकालय के साथ।

कृपया ध्यान दें कि मानकों का क्या होना चाहिए, मेरे अनुभव के संदर्भ में यह कोई जवाब नहीं है। मैंने अतीत में कुछ छोटी गाड़ी / टूटे हुए कंपाइलर और libc कार्यान्वयन से अधिक के साथ काम किया है, इसलिए YMMV। मेरे पास काफी हद तक "सील सिस्टम" पर काम करने का लक्जरी भी है, और किसी भी विशिष्ट एप्लिकेशन के लिए पोर्टेबिलिटी के बारे में चिंतित नहीं है।

गतिशील पुस्तकालयों के बारे में: मैं वर्तमान में खुद इस संबंध में एक चुटकी में हूं; हमारा "ऐप" एक डायनैमिक .so रूप में लोड हो जाता है और हमें किसी भी delete / free रिक्वेस्ट को पास करने के लिए डिफॉल्ट एलोकेशनर के पास जाने में काफी सावधानी बरतनी पड़ती है, अगर वे हमसे नहीं आए। वर्तमान समाधान केवल एक विशिष्ट क्षेत्र में हमारे आवंटन को बंद करने के लिए है: यदि हमें उस पते की सीमा के भीतर से एक डिलीट / फ्री मिलता है, तो हम अपने हैंडलर को भेजते हैं, अन्यथा डिफ़ॉल्ट पर वापस भेज दिया जाता है ... मैंने भी (भयावह) के साथ खिलवाड़ किया है ) कॉल करने वाले के पते की जाँच करने का विचार यह देखने के लिए कि क्या यह हमारे पते की जगह है। (हालांकि, इस तरह के हैक के साथ बूम जाने की संभावना बढ़ जाती है।)

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

(अन्य उत्तरों की प्रतीक्षा में!)





delete-operator