2013-02-22 12 views
6

निम्न कोड में, जब ptr हटा दी जाती है कहा जाता है नहीं है, Base के लिए नाशक कहा जाता है, लेकिन Derived के लिए (के Base आभासी नहीं किया जा रहा नाशक के कारण) नाशक नहीं।विनाश जब नाशक

class Base 
{ 
    int b; 
}; 

class Derived : public Base 
{ 
    int d; 
}; 

int main(void) 
{ 
    Base * ptr = new Derived(); 
    delete ptr; 
    return 0; 
} 

वेलग्रिंड की रिपोर्ट है कि कार्यक्रम कोई स्मृति लीक, जो मैं लगता है कि इस अर्थ में कि सब newed डेटा इस विशेष मामले में हटा दिया जाता है में सच है शामिल हैं। मेरा सवाल यह है कि - Derived के (डिफ़ॉल्ट) विनाशक को नहीं कहा जाता है, d की स्मृति कब और कैसे याद की जाती है?

+3

मेरा मानना ​​है कि स्मृति को 'हटाएं पीटीआर' के कारण पुनः प्राप्त किया गया है, यह केवल इतना है कि विनाशक का आह्वान नहीं किया जाता है, जो एक * संभावित * अपरिभाषित व्यवहार हो सकता है। – iammilind

+5

यह संभावित नहीं है। यह अपरिभाषित व्यवहार है। (§5.3।5/3) –

+2

आपका वालग्रींड कॉल कहता है "कोई मेमोरी लीक नहीं", मेरा 'मेमोरी लॉगर' कहता है '0x3b2380 पर 8 बाइट आवंटित; 0x3b2380 पर 4 बाइट्स को हटा दिया गया; त्रुटि: 4 बाइट अभी भी आवंटित! '। यूबी। संभावित रूप से यह भी कह सकता है कि 'एक अच्छा दिन सर है'। – Zeta

उत्तर

8

पुनः दावा किया जाएगा यह अपरिभाषित व्यवहार एक व्युत्पन्न वर्ग वस्तु के लिए एक आधार वर्ग सूचक की ओर इशारा करते पर delete कॉल करने के लिए अगर आधार वर्ग में नाशक virtual नहीं है।

अपरिभाषित व्यवहार का अर्थ है कि कुछ भी हो सकता है। चाहे मेमोरी लीक हो या न हो, यह तथ्य यह है कि आपका प्रोग्राम कोई व्यवहार दिखा सकता है और आप दिखाए गए किसी भी व्यवहार पर भरोसा नहीं कर सकते हैं।

आपके कोड को मान्य करने के लिए बेस क्लास में विनाशक virtual होना चाहिए।


सी ++ 11 स्टैंडर्ड 5.3.5 हटाएँ:
पैरा 3:

In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

1

अन्य महान लोगों उल्लेख किया है, मानक यह अपरिभाषित व्यवहार है, लेकिन आमतौर पर compilers कि प्रतिस्पर्धा और उन के बारे में परवाह के बीच इस प्रणाली संभाजक कार्यान्वयन, जो मंच के लिए मंच से अलग हो सकता है पर निर्भर है कहते हैं। विनाशक स्वयं Derived ऑब्जेक्ट की स्मृति को मुक्त नहीं करता है, जिसमें फ़ील्ड होते हैं।

जब आप new Derived पर कॉल करते हैं, तो operator new के वैश्विक कार्यान्वयन को कॉल किया जाता है और इसे आवंटित करने के लिए बाइट्स की संख्या प्राप्त होती है। यह आपके मामले में होगा।

वास्तविक मेमोरी फ्रीिंग (वैश्विक operator delete) पर, आवंटक को पता चलेगा कि ऑब्जेक्ट के पते से मुक्त कितने बाइट मुक्त हैं। तो, b और d दोनों द्वारा इस्तेमाल किया स्मृति

+0

नहीं, आप स्मृति को मुक्त करने पर भरोसा नहीं कर सकते हैं। टिप्पणियां सही हैं, यह अनिर्धारित व्यवहार है। आप भविष्यवाणी नहीं कर सकते कि तब क्या होगा। – MSalters

+0

@MSalters हाँ, आप सही हैं। मैंने वर्णन किया कि यह मेरे लिए कैसे काम करता था - यह नहीं पता था कि यह सिर्फ एक सुविधा है .. –

+0

@MSalters: रोमन ने यह बताने की कोशिश की कि इस विशेष परिसर में इस विशेष परिसर में सबसे अधिक संभवतः क्यों हुआ और क्यों वालग्रिंड को किसी भी स्मृति का पता नहीं लगा रिसाव। उसने यह नहीं कहा कि यह यूबी नहीं है। –

2

गलत नाशक कॉलिंग, मुझे लगता है, अपरिभाषित व्यवहार है। आपके पास आभासी विनाशक होना चाहिए।

हालांकि, चूंकि व्युत्पन्न कक्षा के लिए एक ब्लॉक में आवंटन किया जाता है, इसलिए यह "काम करता है" क्योंकि डिलीट के आंतरिक स्थान आवंटन के आकार का ट्रैक रखता है, और इस प्रकार ऑब्जेक्ट लेने वाले 8 बाइटों को मुक्त करता है, बेस के उपयोग के चारों के बजाय।

ध्यान दें कि वर्चुअल विनाशक स्मृति को मुक्त करने के लिए जिम्मेदार नहीं है this अंक। यह विनाशक कहने के बाद delete में होता है।

+0

यह अच्छी तरह से हो सकता है कि डिलीट का यह विशेष कार्यान्वयन आवंटन के आकार का ट्रैक रखता है, लेकिन इसकी आवश्यकता नहीं है और यह तथ्य कि यह काम करने लगता है बस संयोग विशेष रूप से, मेमोरी मैनेजर के पास अक्सर न्यूनतम ब्लॉक आकार होता है जिसे वे आवंटित करेंगे, और यह हो सकता है कि 'व्युत्पन्न' ऑब्जेक्ट के लिए आवंटित ब्लॉक 'बेस' ऑब्जेक्ट के लिए आवंटित ब्लॉक के समान आकार हो। किसी भी घटना में, अपरिभाषित व्यवहार बस अपरिभाषित है; इस बारे में अटकलें कि किसी विशेष मामले में लक्षण न दिखाने का कारण आमतौर पर अनुमान लगाया जा सकता है। –

+0

ओह, और जब मैं इस विषय पर हूं, स्मृति को मुक्त करना अक्सर विनाशक में किया जाता है; यह एक गुप्त झंडा मिलता है जो यह बताता है कि स्मृति को भी हटाना है या नहीं। इससे क्लास-विशिष्ट 'ऑपरेटर डिलीट' और व्युत्पन्न प्रकारों के विभिन्न आकारों से निपटना आसान हो जाता है। व्याख्यान के बारे में खेद है ... –

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