मैंने सरणी के अंत में एक संख्या जोड़ने के लिए push_back फ़ंक्शन बनाया है। लेकिन मुझे लगता है कि नीचे इस कोड में लीक होने के कुछ कारण हैं। क्या आप कारणों का पता लगा सकते हैं?

void ElasticArray::push_back(int item){
    
    if(_max_size == _size){
        int* tmpArray = nullptr;
        tmpArray = new int[_size * 2];
        for(int i = 0; i < _size; i++){
            tmpArray[i] = _array[i];
        }
        _array = tmpArray;
        _max_size = _size * 2;
        delete[] tmpArray;
        tmpArray = nullptr;
    }

    else if(_max_size == 0){
        _max_size = 16;
    }

    if(_max_size > _size){
        _array[_size] = item;
        _size++;
    }
    
    _array[_size] = item;
    _size++;
}
c++
-1
Johny 14 फरवरी 2021, 07:48

2 जवाब

सबसे बढ़िया उत्तर

आपका पूरा फ़ंक्शन सभी गलत कोडित है। आपके चरों के कुप्रबंधन के कारण इसमें कई समस्याएं हैं, इस प्रकार एक स्मृति रिसाव, एक बफ़र ओवरफ़्लो, और अपरिभाषित व्यवहार का कारण बनता है।

यदि _max_size 0 है, तो संभवतः _size भी 0 है (अन्यथा आपके कोड में कहीं और बग हैं), और आप 0 तत्वों को आवंटित करते हैं। _max_size को कभी भी 16 पर सेट होने का मौका नहीं मिलता। लेकिन अगर, किसी कारण से, _max_size 0 था लेकिन _size नहीं था, तो _max_size 16 पर सेट हो जाएगा लेकिन _array को इंगित करने के लिए वास्तव में कुछ भी आवंटित नहीं होगा, जिससे _array की सामग्री के बाद के उपयोग पर अपरिभाषित व्यवहार हो।

भले ही आपने कुछ आवंटित किया हो, आप _array पर delete[] को कॉल करने से पहले _tmpArray को _array असाइन कर रहे हैं, जिससे रिसाव हो रहा है। और फिर आप delete[] को उस मेमोरी पर कॉल करते हैं जिसे आपने अभी-अभी _array को असाइन किया है, जिससे _array की सामग्री के बाद के एक्सेस पर अधिक अपरिभाषित व्यवहार होता है।

इससे भी बदतर, भले ही आप सरणी को ठीक से बढ़ा रहे हों, आप प्रत्येक item को दो बार सरणी में धकेल रहे हैं, क्योंकि if(_max_size > _size) कोड में उस बिंदु तक हमेशा सत्य होगा (यदि आप बाकी सब कुछ सही ढंग से कर रहे हैं), जो अंततः बफर ओवरफ्लो, स्मृति को दूषित करने का कारण बन जाएगा।

इसके साथ ही, इसके बजाय इसे आजमाएं:

void ElasticArray::push_back(int item){
    
    if ((_max_size == _size) || (_max_size == 0)){
        int new_max = (_max_size != 0) ? (_max_size * 2) : 16;
        int* tmpArray = new int[new_max];
        for(int i = 0; i < _size; ++i){
            tmpArray[i] = _array[i];
        }
        delete[] _array;
        _array = tmpArray;
        _max_size = new_max;
    }
    
    _array[_size] = item;
    _size++;
}
2
Remy Lebeau 14 फरवरी 2021, 12:47

आप _array = tmpArray असाइन कर रहे हैं और उसके बाद tmpArrary पर आपकी कॉलिंग डिलीट हो जाती है फिर आप _array तक पहुंच रहे हैं

        _array = tmpArray;
        _max_size = _size * 2;
        delete[] tmpArray;
        tmpArray = nullptr;

_array tempArray द्वारा इंगित मेमोरी लोकेशन के प्रारंभ पते को संग्रहीत करता है

उदाहरण: यदि प्रारंभ स्मृति tempArray का स्थान 0x00f39f38 है तो उसके बाद

_array = tmpArray;

_array 0x00f39f38 को भी इंगित करेगा

तो जब आप कॉल करते हैं

delete tmpArray
tmpArray = nullptr;

TempArray शून्य 0x00000000 को इंगित करना शुरू कर देता है लेकिन पता जो _array द्वारा इंगित किया जाता है वह अभी भी 0x00f39f38 है, इसलिए जब आप ऐसा करते हैं

_array[_size] = item;
    _size++;

आपको ओएस और कंपाइलर के आधार पर एक अपरिभाषित व्यवहार मिलेगा

सुझाव

Std::vectors का उपयोग करें या _array=tempArray . करते समय एक गहरी प्रतिलिपि करें

0
User 14 फरवरी 2021, 11:54