2014-08-29 7 views
11

नीचे दिए गए कोड के लिए: (1) "मुख्य" एक फ़ंक्शन "f1" कहता है। (2) फ़ंक्शन "एफ 1" कुछ संख्या क्रंचिंग करता है; malloc के साथ "char" की एक सरणी बनाता है और फिर, सरणी के सूचक को मुख्य पर लौटाता है (बिना आवंटन-मुक्त-सरणी के)।क्या फ़ंक्शन में आवंटित स्मृति अभी भी फ़ंक्शन रिटर्न के बाद आवंटित रहती है?

मैं 3 मामले से संबंधित प्रश्न हैं:, (1) मुझे लगता है हालांकि समारोह "F1" समाप्त कर दिया है, आवंटित चार सरणी अभी भी जब तक मुख्य कार्यक्रम पूरी तरह से समाप्त हो जाता है आवंटित रहता है। यही है, आवंटित स्मृति अभी भी मुख्य से संबंधित है और कोई अन्य प्रक्रिया इसे बाहर से (मेरा मतलब है, हस्तक्षेप नहीं कर सकती)। क्या मैं सही हू? (2) क्या प्रोग्राम समाप्त होने से पहले मुझे सरणी ("एफ 1" में आवंटित) को मुक्त करना होगा (या जैसे ही यह मुख्य प्रोग्राम समाप्त हो जाता है)? (3) यदि दूसरे प्रश्न का उत्तर "हां" है तो आप किसी अन्य फ़ंक्शन में आवंटित सरणी को कैसे मुक्त करते हैं?

नोट: मैं शुद्ध सी की सीमाओं के भीतर रहना चाहता हूं और सी ++ तक नहीं पहुंचना चाहता हूं।

char *f1 (...) { 
    ... 
    ... 
    char *fTmp = malloc (length1 * sizeof (char)); 
    char *fData = malloc (length2 * sizeof (char)); 
    ... 
    ... 
    free (fTmp); 
    return (fData); 
} 

int main() { 
    char *fData = f1 (...); 
    ... 
    return (0); 
} 

उत्तर

14

मुझे लगता है, हालांकि फ़ंक्शन "एफ 1" समाप्त हो गया है, आवंटित चार सरणी तब भी आवंटित रहती है जब तक कि मुख्य प्रोग्राम पूरी तरह से समाप्त नहीं हो जाता।

सच। गतिशील रूप से आवंटित स्मृति में कार्यों के साथ कुछ लेना देना नहीं है, यह प्रक्रिया से संबंधित है।

यही है, आवंटित स्मृति अभी भी मुख्य से संबंधित है और कोई अन्य प्रक्रिया इसे बाहर से एक्सेस नहीं कर सकती है। क्या मैं सही हू?

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

क्या प्रोग्राम को समाप्त होने से पहले मुझे सरणी ("एफ 1" में आवंटित) को मुक्त करना होगा (या जैसे ही यह मुख्य प्रोग्राम समाप्त हो जाता है)?

हां। अनियंत्रित स्मृति - अधिकांश सिस्टमों में - प्रक्रिया समाप्त होने पर स्वचालित रूप से ऑपरेटिंग सिस्टम द्वारा डिलीकेट किया जाता है लेकिन यह सिस्टम निर्भर है। आईएमओ जब भी ओएस करता है तो आपको हमेशा एक लाल झंडे के रूप में इस तरह के स्वचालित डीलोकेशन का उपयोग करके निरस्त करना चाहिए (मैं भूल जाता हूं कि इसे हटाना, क्या यह एक बग है? कुछ मुझे याद आया?)। इसके अलावा यदि f1 1000 बार बुलाया जाता है तो यह हर बार उपलब्ध सभी स्मृति को तुरंत याद कर देगा। किसी सर्वर में किसी प्रक्रिया के बारे में सोचें, यह हो सकता है (और चाहिए) वर्षों तक चल रहा है और चल रहा है।

यदि दूसरे प्रश्न का उत्तर "हां" है तो आप किसी अन्य फ़ंक्शन में आवंटित सरणी को कैसे मुक्त करते हैं?

यह अच्छा है जब स्मृति आवंटित करता है तो यह भी मुक्त होता है। यदि यह संभव नहीं है तो कॉलर ऐसी स्मृति के लिए जिम्मेदार बन जाएगा। उदाहरण के लिए, strdup() क्या करता है। ऐसे मामले में फ़ंक्शन को आवंटित स्मृति (या किसी हैंडल/टोकन जिसे किसी अन्य विशेष फ़ंक्शन द्वारा उपयोग किया जा सकता है) को पॉइंटर लौटा देना चाहिए (किसी भी तरह)। उदाहरण के लिए:

char* pBuffer = f1(); 
// Use it 
free(pBuffer); 

नोट यदि आप इस तरह आंतरिक सूचक छुपाना चाहते हैं कई कई तकनीकों देखते हैं कि।आप एक टोकन (उदाहरण के लिए एक पूर्णांक, एक शब्दकोश में कुंजी), typedef या एक अपारदर्शी प्रकार का उपयोग कर सकते हैं।

+1

मैं वही कर रहा था; यानी, मैंने सरणी को एक प्रक्रिया में मुक्त कर दिया है जो कि किसी अन्य प्रक्रिया में बनाया गया है ** ** के माध्यम से पॉइंटर का उपयोग करके। मुझे यकीन नहीं था कि मैं जो कर रहा हूं वह सही तरीका था। तो, आपका दृष्टिकोण निकटतम उत्तर लगता है: "यह अच्छा है जब स्मृति आवंटित करता है, यह भी मुक्त होता है। यदि यह संभव नहीं है तो कॉलर ऐसी स्मृति के लिए जिम्मेदार बन जाएगा।" – ssd

+1

@ merkez3110 लेकिन आप प्रक्रियाओं के बीच पॉइंटर्स साझा नहीं कर सकते (जब तक कि आप सुरक्षित वर्चुअल मेमोरी के बिना किसी वातावरण में नहीं चल रहे हों)। –

+1

गलत शब्दावली का उपयोग करने के लिए मुझे क्षमा करें: "प्रक्रिया"। ऊपर मेरी टिप्पणी में, मैं वास्तव में एक ही कार्यक्रम के भीतर अलग-अलग "कार्यों" का मतलब था, अलग-अलग प्रक्रियाओं में नहीं। सभी के लिए धन्यवाद। – ssd

1

malloc का उपयोग करते हुए जब तक यह आप free यह ढेर पर स्मृति आवंटित करेगा।

इसका मतलब है कि आपको यह सुनिश्चित करने की आवश्यकता है कि प्रत्येक मॉलोक के पास एक समान नि: शुल्क है, यह भी निहित नहीं है कि कोई अन्य प्रक्रिया आपके डेटा तक नहीं पहुंच सकती है। यह एक पते पर सिर्फ एक मूल्य है।

मेमोरी लीक से बचने के लिए आपको अपने मुख्य में free(fData) होना चाहिए।

तो सारांश में:

1) आपका पहला धारणा सही है, दूसरे और तीसरे नहीं है। यह आवंटित रहेगा, लेकिन यह मुख्य के लिए स्थानीय नहीं है, और प्रक्रिया से बंधे नहीं है क्योंकि यह को समाप्त करता है।

2) हाँ, आप इसे

3) सूचक आप समारोह से मिल का उपयोग करें खाली करना होगा। यदि आप फ़ंक्शन से आवंटित डेटा पर पॉइंटर वापस नहीं करते हैं, तो सुनिश्चित करें कि free फ़ंक्शन है।

1
  1. हां, यह अभी भी ढेर में है। हालांकि, आप प्रक्रिया की अवधारणा के बारे में भ्रमित हैं। जब तक आप एक और प्रक्रिया नहीं बनाते (* nix पर fork का उपयोग करके), यह अभी भी वही प्रक्रिया है।

  2. जब इसका उपयोग नहीं किया जाता है तो स्मृति को मुक्त करने की अच्छी आदत है। लेकिन यदि कार्यक्रम सामान्य रूप से समाप्त हो जाता है, तो आवंटित स्मृति प्रणाली द्वारा मुक्त हो जाती है।

  3. इस तरह

    :

    int main() { 
        char *fData = f1 (...); 
        //... 
        free(fData); 
        //... 
    } 
    
4
  1. जब तक यह मुक्त हो जाता है हाँ, स्मृति malloc() रहता है के साथ आवंटित। एक फ़ंक्शन कभी भी अपने कॉलर को परिवर्तनीय आकार का डेटा कैसे लौटा सकता है?

  2. जब कोई प्रोग्राम निकलता है, तो malloc() के साथ आवंटित सभी मेमोरी मुक्त हो जाती है। हालांकि, कार्यक्रम समाप्त होने तक बहुत सारी अनियंत्रित स्मृति को रखना आम तौर पर एक अच्छा विचार नहीं है, क्योंकि यह प्रदर्शन को प्रभावित कर सकता है, या सिस्टम वर्चुअल मेमोरी से बाहर हो सकता है। यह लंबे समय से चलने वाले कार्यक्रमों के लिए एक विशेष चिंता हो सकती है, जब तक वे सभी उपलब्ध वर्चुअल मेमोरी का उपयोग नहीं करते हैं, तब तक उनकी स्मृति उपयोग कभी-कभी बढ़ती रहती है।

  3. आप फ़ंक्शन द्वारा लौटे गए पॉइंटर पर free() पर कॉल करते हैं। तो आपके मामले में, main() सरणी का उपयोग करके किए जाने के बाद free(fData) कर सकता है।

यह सभी किसी भी सी प्रोग्रामिंग कक्षा या पाठ्यपुस्तक में शामिल होना चाहिए।

2

malloc ढेर पर स्मृति आवंटित करता है और इसलिए यह स्मृति तब तक आवंटित की जाती है जब तक इसे free फ़ंक्शन या प्रोग्राम सफलतापूर्वक समाप्त नहीं किया जाता है।
अपने मामले में आपने ftemp को f1 में मुक्त किया है, इसलिए यह कार्य समाप्त होने के बाद मौजूद नहीं है। fdata अभी भी ढेर पर है और यह main तक पहुंच योग्य है क्योंकि आप उस आवंटित स्थान पर पॉइंटर लौट रहे हैं।

एक बार main सफलतापूर्वक समाप्त हो जाता है, fdata द्वारा निर्देशित स्मृति मुक्त हो जाती है।

तो, जैसे ही आपको इसकी आवश्यकता नहीं है, इसे मुफ्त मेमोरी के लिए अच्छा माना जाता है। किसी प्रोग्राम के अंत में ब्लॉक को मुक्त करने में कोई बात नहीं है, क्योंकि प्रक्रिया समाप्त होने पर (प्रोग्रामिंग आधुनिक ऑपरेटिंग सिस्टम पर विचार करते समय) सभी प्रोग्राम की जगह सिस्टम को वापस दी जाती है।

1

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

दोनों पर थोड़ा सा पढ़ने से आपको समझने में मदद मिलेगी। मैं इंगित करता हूं कि आपके पास एफडीएटा के दो उदाहरण हैं, प्रत्येक के अपने स्वयं के दायरे के साथ। दोनों पॉइंटर्स आपके द्वारा आवंटित स्मृति को इंगित करते हैं:

char *fData = malloc (length2 * sizeof (char)); 

.. भले ही वे आपके कोड निष्पादित होने के दायरे में और बाहर हो जाएं।

1

यदि आप स्मृति मुक्त नहीं करते हैं तो आप इसका उपयोग नहीं कर रहे हैं, अंत में यह जमा हो जाएगा- यदि आपने इसे कई अन्य पॉइंटर्स के साथ किया- और आपका प्रोग्राम स्मृति से बाहर हो सकता है। free फ़ंक्शन का उपयोग करके मेमोरी ब्लॉक को खाली करने के बाद, मैं सूचकांक को NULL असाइन करने का भी सुझाव दूंगा क्योंकि यह पॉइंटर्स को खतरे में डाल देता है, भले ही आपने पॉइंटर को मुक्त किया हो, भले ही आप इसे एक्सेस करने का प्रयास करें, तो आप अपरिभाषित व्यवहार प्राप्त कर सकते हैं, जबकि एक्सेस और NULL पॉइंटर्स पर ऑपरेशन एक क्रैश में परिणामस्वरूप होता है, इसलिए आप आसानी से समस्या का पता लगाने में सक्षम होंगे

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