2009-04-21 8 views
6

मेरे स्टैक आधारित आवंटक के लिए कोई सुझाव? (सिवाय सुझाव निजी/सार्वजनिक सदस्यों के साथ एक वर्ग का उपयोग करने के लिए)इस सी ++ स्टैक आवंटक के लिए सुधार?

struct Heap 
{ 
    void* heap_start; 
    void* heap_end; 
    size_t max_end; 

    Heap(size_t size) 
    { 
     heap_start = malloc(size); 
     heap_end = heap_start; 
     max_end = size + (size_t) heap_start; 
    } 

    ~Heap() 
    { 
     ::free(heap_start); 
    } 

    void* allocate(size_t bytes) 
    { 

     size_t new_end = ((size_t) heap_end) + bytes; 

     if(new_end > max_end) 
      throw std::bad_alloc(); 

     void* output = heap_end; 
     heap_end = (void*) new_end; 
     return output; 
    } 

} 
+0

मेरा सी ++ मेमोरी पूल कैसा है? – paxdiablo

+0

बस सोच रहा है कि इसे अनुकूलित करने का कोई तरीका है या बेहतर सम्मेलन आदि .. – Unknown

+0

ठीक है, इसे स्पष्ट करने के लिए शीर्षक को ठीक करना। – paxdiablo

उत्तर

4

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

Here's one आप एक गाइड के रूप में उपयोग कर सकते हैं। यह आपके जैसा ही है, लेकिन आवंटित नोड्स पर मूल इटरेटर्स शामिल है, और टेम्पलेट्स को जागरूक करने के लिए उपयोग करता है।

+0

आह हाँ, यह सही शब्द प्रतीत होता है। मैंने सोचा कि इसे मेमोरी पूल कहा जाता था। – Unknown

2

दो स्पष्ट समस्याओं:

1/तुम एक deallocate() जरूरत नहीं है।

2/ए deallocate() आपकी वर्तमान रणनीति के साथ लिखना बहुत कठिन होगा जबतक कि आप हमेशा आवंटित करने के सटीक रिवर्स ऑर्डर में डिलीकेट नहीं करेंगे। आपको उस मामले को पूरा करने की आवश्यकता होगी जहां कोई ग्राहक आपके उपयोग किए गए अनुभाग के बीच में स्मृति को हटाना चाहता है।

बेशक, यदि आप रिवर्स ऑर्डर में डिलीकेट करते हैं, (2) कोई समस्या नहीं है। और यदि आप कभी भी स्मृति मुक्त नहीं करते हैं, (1) भी कोई समस्या नहीं है।

यह इस बात पर निर्भर करता है कि आप क्या करना चाहते हैं।

+0

एक सामान्य मेमोरी पूल के रूप में, आप केवल ऑब्जेक्ट्स का एक गुच्छा आवंटित करते हैं, और फिर उन्हें 1 फ़ंक्शन कॉल में सभी को डिलीकेट करते हैं। लेकिन फिर मैं पूरी तरह से तीक्ष्णक बिंदु के बारे में भूल गया कि अगर वे पीओडी नहीं हैं तो मुझे उनके प्रत्येक विनाशकों को फोन करने की आवश्यकता हो सकती है। – Unknown

+0

आपको केवल विनाशकों को कॉल करने की आवश्यकता है यदि उनके पास फाइल हैंडल/अन्य ऑब्जेक्ट्स हैं जो पूल में नहीं रहते हैं। अगर सब कुछ केवल स्मृति को आवंटित करता है और वह स्मृति पूल में है, तो आपको विनाशकों को कॉल करने की सख्ती से आवश्यकता नहीं है। –

1

आपका ढेर डीलोकेशन की अनुमति नहीं देता है। सी ++ में नया के साथ आवंटित ऑब्जेक्ट्स के लिए आप इसका उपयोग कैसे करेंगे?

+0

मुझे लगता है कि आप एक अच्छा मुद्दा उठाते हैं, मैं केवल पीओडी रखने की सोच रहा था। – Unknown

+0

पीओडी के साथ भी आपको ऑपरेटर हटाने का ख्याल रखना होगा।यदि आप ऐसा नहीं करते हैं, तो डिफ़ॉल्ट ऑपरेटर डिलीट का उपयोग किया जाएगा जो आपके प्रोग्राम को क्रैश कर देगा। – sharptooth

+0

आप क्या सलाह देते हैं? क्या मुझे वैश्विक डिलीवरी ऑपरेटर को ओवरराइड करने की आवश्यकता होगी? – Unknown

4
size_t new_end = ((size_t) heap_end) + bytes; 

अच्छा नहीं, कभी नहीं है कि तरह बातें करते हैं, आप को लगता है कि sizeof (size_t) == sizeof (शून्य *), भी क्या हुआ अगर bytes==(size_t)(-1) इस

साथ ही काम नहीं होता है, होता है आपको यह सुनिश्चित करने की ज़रूरत है कि आपके द्वारा वापस आने वाले पॉइंटर्स गठबंधन किए गए हैं। अन्यथा आपको समस्याएं होंगी। इसलिए आपको यह सुनिश्चित करने की ज़रूरत है कि बाइट्स आपके प्लेटफ़ॉर्म के अनुसार 4 या 8 के एकाधिक हैं।

class {... 
char *max_end,*head_end,*heap_start; 
}; 

... 
max_end=heap_start+size; 
... 
bytes=align_to_platform_specific_value(bytes); 
if(max_end-heap_end >= bytes) { 
    void* output = (void*)heap_end; 
    heap_end+=bytes; 
    return output; 
} 
throw std::bad_alloc(); 

सुझाव? पहिया को पुन: पेश न करें। कई और अच्छे पूल पुस्तकालय हैं।

+0

लेकिन कारण मैंने char का उपयोग नहीं किया क्योंकि कारण 1 बाइट होने की गारंटी नहीं है। मेरे ज्ञान के लिए size_t हमेशा शून्य है * क्योंकि एक प्रकार पूरे पता स्थान को फैला सकता है। इसके अलावा मेरा जीसीसी कंपाइलर मुझे शून्य * अंकगणित करने की अनुमति नहीं देता है। लेकिन आपके पास संरेखण के साथ एक बिंदु है: यह एक अंतरिक्ष/समय व्यापार है। – Unknown

+1

मानक defiantly आकार (char) = 1 परिभाषित करता है, मानक आकार (size_t) == आकार (शून्य *) को परिभाषित नहीं करता है, यह अभ्यास में भी आम है, लेकिन यह आकार (intptr_t) == आकार (शून्य *) (लेकिन आकार को परिभाषित करता है) intptr_t कुछ कंप्यूटर्स जैसे वीसी ++ के लिए उपलब्ध नहीं है)। – Artyom

+0

"यह एक अंतरिक्ष/समय व्यापार है।" यह सहीता सवाल है। कुछ प्लेटफार्मों (जैसे एआरएम) पर यदि आप अनचाहे पहुंच करते हैं तो एक प्रक्रिया विफल हो सकती है। साथ ही, आपका डेटा परमाणु संचालन का उपयोग करता है (उदाहरण के लिए म्यूटेक्स) यदि यह असाइन नहीं किया गया है तो यह खराब होगा। – Artyom

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