2013-02-17 16 views
5

मैं इस प्रश्न से खुद को निम्नलिखित कार्यक्रम के बारे में उलझन में छुटकारा पाने के लिए कह रहा हूं। मुझे पता है कि कुछ संदर्भों में एक सरणी का उपयोग करके सरणी को अपने पहले तत्व में एक पॉइंटर को क्षय करने में मदद मिलेगी। मेरे पास एक ऐसा फ़ंक्शन है जो पॉइंटर द्वारा इस सरणी को लौटाता है (यह फ़ंक्शन new[] का उपयोग करके बनाया गया है)। क्या सरणी क्षय हो जाएगी, जिसके कारण पॉइंटर केवल पहले तत्व को इंगित करेगा? यहां एक उदाहरण दिया गया है:क्या किसी फ़ंक्शन से गतिशील रूप से आवंटित सरणी लौटने से मेमोरी लीक हो जाती है?

int *foo() { 
    int *t = new int[10]; 

    return t; 
} 

int main() { 
    int *p = foo(); 
} 

यह वह जगह है जहां भ्रम का अनुसरण होता है। मुझे नहीं पता कि p पहले तत्व या पूरे सरणी को इंगित करता है। तो मेरे पास निम्नलिखित प्रश्न हैं:

  • सूचक द्वारा सरणी को वापस करने से इसका क्षय होता है (और इसके परिणामस्वरूप स्मृति रिसाव होता है)?
  • क्या p सरणी के पहले तत्व को इंगित करता है?
  • delete[]p पर उपयोग नहीं किया गया है यदि उपरोक्त दो सत्य हैं तो अपरिभाषित व्यवहार का कारण बनता है?

मुझे उम्मीद है कि इन सवालों का उत्तर दिया जा सकता है, इसलिए मैं इस कार्यक्रम को पूरी तरह से समझ सकता हूं। धन्यवाद।

+1

यदि आपकी अगली पंक्ति 'p = '' या कुछ है, तो आप foo से लौटाए गए पॉइंटर को" खो देंगे ", और बूम ... मेमोरी लीक। यदि आप आवंटित किसी भी स्मृति को साफ करने की उपेक्षा करते हैं तो यह केवल एक स्मृति रिसाव है। और उस हिस्से का हिस्सा उस स्मृति को "भूलना" या "खोना" पॉइंटर्स हो सकता है। –

+0

"क्षय" गतिशील भंडारण अवधि के साथ बनाई गई वस्तुओं पर कुछ भी नहीं करता है। यह सिर्फ कुछ ऐसा वर्णन करता है जो सरणी अभिव्यक्तियों के साथ होता है, जो उन्हें पॉइंटर प्रकार के रूप में व्यवहार करता है। – aschepler

+0

मेमोरी लीक इस बारे में नहीं हैं कि आप अपने आवेदन में पॉइंटर्स कैसे पास करते हैं, लेकिन यह सुनिश्चित है कि आप कैसे सुनिश्चित करते हैं ("इसे प्रबंधित करें") कि आवंटित की गई सभी मेमोरी को भी हटा दिया जा रहा है। मेमोरी मैनेजमेंट जितना आसान होगा, उतना कम मौका है कि आपके कोड में मेमोरी रिसाव है ~> तो बस [RAII] (http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) जितना संभव हो उसका पालन करें :) – LihO

उत्तर

6

आपका फ़ंक्शन मेमोरी आवंटित करता है और इसे पहले तत्व के रूप में पहले तत्व के लिए, या अधिक तकनीकी रूप से देता है।

बाद में स्मृति के साथ क्या होता है कॉलर तक।इसका अर्थ यह है कि जब सरणी लौटाई जाती है तो अब इसका उपयोग नहीं किया जाता है, इसे delete[] का उपयोग करके कॉलर द्वारा हटाया जाना चाहिए। यदि कॉलर इस नियम का सम्मान नहीं करता है, तो प्रोग्राम स्मृति को रिसाव करता है। यदि आप इस तरह के कोड लिखते हैं, तो आपको अपनी विधि के दस्तावेज़ीकरण में दृढ़ता से जोर देना चाहिए!

इस तरह की चीजों के लिए अधिक आधुनिक समाधान स्मार्ट पॉइंटर्स का उपयोग करना है। स्मार्ट पॉइंटर्स स्वयं ऑब्जेक्ट्स (पॉइंटर्स को नहीं) हैं जो एक अंतर्निहित पॉइंटर की रक्षा करते हैं। स्मार्ट पॉइंटर के प्रकार के आधार पर हम यहां बात कर रहे हैं, कॉलर में स्कोप से बाहर होने पर इसे स्वचालित रूप से हटा दिया जाएगा (जो आवंटित स्मृति को स्वामित्व रखता है), या जब इसका उपयोग अब दूसरों द्वारा नहीं किया जाता है (साझा स्वामित्व) ।

जानकारी के लिए इस सवाल देखें: smart pointers and arrays

अब समारोह में अपने प्रश्न में की तरह लिखा गया था, तो, तो यह एक स्मार्ट एक के बजाय एक कच्चे सूचक देता है, तो आप अभी भी भीतर स्मार्ट संकेत की क्षमताओं का उपयोग कर सकते बाद में सरणी लपेटकर कॉलर।

तत्वों की संख्या/स्मृति की मात्रा को हटाने के लिए, यह delete[] के कार्यान्वयन के लिए पूरी तरह से है, इसलिए आपको कॉलर में तत्वों की संख्या के बारे में चिंता करने की आवश्यकता नहीं है। हालांकि, आप उनके साथ काम करने के लिए तत्वों की संख्या से भी सवाल नहीं उठा सकते हैं। यदि आपको तत्वों की संख्या की आवश्यकता है, तो आपको उन्हें "आउट पैरामीटर" के माध्यम से भी वापस करना होगा।

आधुनिक सी ++ में, मैं दृढ़ता से कच्चे सरणियों से अलग, उदाहरण के लिए std::vector, या std::map की तरह अगर आप एक साहचर्य कंटेनर की जरूरत है, और इस तरह के रूप में समस्याओं डेटा संरचनाओं के उपयोग की सलाह "ने इस आबंटित स्मृति को हटा देता है?" चले गए हैं।

7

सूचक द्वारा सरणी को वापस करने से इसका क्षय होता है (और इसके परिणामस्वरूप स्मृति रिसाव हो सकता है)?

आप वास्तव में t की प्रतिलिपि लौट रहे हैं, जो एक सूचक है। यह पहले से ही एक गतिशील आवंटित सरणी के पहले तत्व पर इंगित करता है। यदि आप delete [] पर कॉल करने में विफल रहे तो केवल एक स्मृति रिसाव होगी।

क्या पी सरणी के पहले तत्व को इंगित करता है?

हाँ

उपरोक्त दो सत्य हैं, तो हटाना [] पी कारण अपरिभाषित व्यवहार पर का उपयोग कर रहा है?

नहीं, ऐसा करना ठीक है। जब तक कार्य एक गतिशील आवंटित सरणी में सूचक को वापस कर रहा है।

आपने इस मुहावरे के साथ एक गंभीर समस्या की पहचान की है: आप यह नहीं जान सकते कि क्या आप किसी तत्व के लिए पॉइंटर प्राप्त कर रहे हैं, एक गतिशील आवंटित सरणी के पहले तत्व के लिए एक सूचक, वैश्विक के लिए एक सूचक। आप फ़ंक्शन के रिटर्न प्रकार को देखकर नहीं जान सकते हैं कि आपको delete, delete [] पर कॉल करने की आवश्यकता है या कॉल को बिलकुल भी कॉल नहीं करना है। समाधान: एक सूचक वापस मत करो! एक प्रकार लौटाएं जो कि बीयर व्यक्त करता है कि क्या हो रहा है, और यह अपने संसाधनों (std::vector, std::array, std::unique_ptr, std::shared_ptr ...) प्रबंधित करने का ख्याल रखता है।

0

क्या उपरोक्त दो सत्य हैं तो हटाए गए [] पर p का उपयोग अपरिभाषित व्यवहार का उपयोग करते हैं?

नहीं, हटाएं नहीं [] पी मेमोरी लीक में परिणाम देगा!

हालांकि, [] हटाना जादुई जानता है कि कब तक सरणी, sizeof करता है (पी) नहीं, क्योंकि संभाजक आबंटित स्थान का ट्रैक रखता है। हालांकि आकार संकलित समय पर उत्पन्न एक निश्चित मान है

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