मुफ्त के बाद NULL में परिवर्तनशील चर


156

मेरी कंपनी में एक कोडिंग नियम है जो कहता है कि किसी भी मेमोरी को मुक्त करने के बाद, चर को रीसेट करें NULL। उदाहरण के लिए ...

void some_func () 
{
    int *nPtr;

    nPtr = malloc (100);

    free (nPtr);
    nPtr = NULL;

    return;
}

मुझे लगता है कि, ऊपर दिखाए गए कोड जैसे मामलों में, सेटिंग का NULLकोई अर्थ नहीं है। या क्या मैं कुछ न कुछ भूल रहा हूं?

यदि ऐसे मामलों का कोई अर्थ नहीं है, तो मैं इस कोडिंग नियम को हटाने के लिए "गुणवत्ता टीम" के साथ इसे लेने जा रहा हूं। कृपया सलाह दें।


2
यह हमेशा उपयोगी होता है कि यदि ptr == NULLइसके साथ कुछ भी करने से पहले यह जांचने में सक्षम हो। यदि आप अपने फ्री होल्ड पॉइंट्स को कम नहीं करते हैं, तो आपको ptr != NULLअभी भी अनुपयोगी पॉइंटर मिलेगा ।
की जेई

डैंगलिंग पॉइंटर्स उपयोग-बाद-मुक्त जैसे शोषणकारी कमजोरियों को जन्म दे सकते हैं।
Константин Ван

जवाबों:


285

अप्रयुक्त बिंदुओं को NULL पर सेट करना एक रक्षात्मक शैली है, जो कि पॉइंटर पॉइंटर बग्स से बचाता है। यदि एक झूलने वाला पॉइंटर मुक्त होने के बाद एक्सेस किया जाता है, तो आप यादृच्छिक मेमोरी को पढ़ या अधिलेखित कर सकते हैं। यदि कोई नल पॉइंटर एक्सेस किया गया है, तो आपको अधिकांश सिस्टम पर तत्काल दुर्घटना मिलती है, जो आपको बताती है कि त्रुटि क्या है।

स्थानीय चर के लिए, यह थोड़ा स्पष्ट हो सकता है यदि यह "स्पष्ट" है कि सूचक मुक्त होने के बाद अब तक पहुँचा नहीं है, इसलिए यह शैली सदस्य डेटा और वैश्विक चर के लिए अधिक उपयुक्त है। स्थानीय चर के लिए भी, यह एक अच्छा तरीका हो सकता है यदि मेमोरी जारी होने के बाद फ़ंक्शन जारी रहता है।

शैली को पूरा करने के लिए, आपको पॉइंटर्स को इनिशियलाइज़ करना चाहिए, इससे पहले कि वे एक सच्चे पॉइंटर वैल्यू असाइन करें।


3
मुझे समझ में नहीं आता है कि "सही संकेत सूचक मान प्राप्त करने से पहले आप पॉइंटर्स को NULL को इनिशियलाइज़ क्यों करेंगे"?
पॉल बिगगर

26
@Paul: विशिष्ट मामले में, घोषणापत्र पढ़ सकता है int *nPtr=NULL;। अब, मैं इस बात से सहमत होता हूँ कि यह निरर्थक होगा, अगली पंक्ति में एक मॉलॉक के ठीक बाद। हालाँकि, यदि घोषणा और पहली इनिशियलाइज़ेशन के बीच कोड है, तो कोई व्यक्ति वैरिएबल का उपयोग करना शुरू कर सकता है, भले ही उसका कोई मूल्य न हो। यदि आप अशक्त करते हैं, तो आपको segfault मिलता है; बिना, आप फिर से यादृच्छिक मेमोरी पढ़ या लिख ​​सकते हैं। इसी तरह, यदि चर को बाद में केवल सशर्त रूप से आरंभ किया जाता है, तो बाद में दोषपूर्ण पहुंच आपको तत्काल दुर्घटनाग्रस्त हो सकती है यदि आपको अशक्त होना याद है।
मार्टिन वी। लोविस

1
मुझे व्यक्तिगत रूप से लगता है कि किसी भी गैर-तुच्छ कोडबेस में डेरेफ्रेंसिंग नल के लिए एक त्रुटि प्राप्त करना उतना ही अस्पष्ट है जितना कि आपके पास कोई पता नहीं है। मैं व्यक्तिगत रूप से कभी परेशान नहीं करता।
विल्हेमटेल

9
विल्हेम, मुद्दा यह है कि एक अशक्त सूचक के साथ आप एक दृढ़ दुर्घटना और समस्या का वास्तविक स्थान प्राप्त करते हैं। एक खराब पहुंच दुर्घटनाग्रस्त हो सकती है और अप्रत्याशित स्थानों में अप्रत्याशित तरीकों से डेटा या व्यवहार को दूषित नहीं कर सकती है।
अमित नायडू

4
दरअसल, पॉइंटर को NULL से शुरू करने में कम से कम एक महत्वपूर्ण खामी है: यह कंपाइलर को आपको अनइंस्टॉल किए गए वैरिएबल के बारे में चेतावनी देने से रोक सकता है। जब तक आपके कोड का तर्क वास्तव में सूचक के लिए उस मूल्य को स्पष्ट रूप से संभालता है (यानी अगर (nPtr == NULL) dosomething ...) तो इसे छोड़ना बेहतर है।
एरिक

37

पॉइंटर को NULLबाद में सेट करना एक freeसंदिग्ध अभ्यास है जो अक्सर एक "अच्छे प्रोग्रामिंग" नियम के रूप में लोकप्रिय रूप से झूठे आधार पर लोकप्रिय होता है। यह उन नकली सच्चाइयों में से एक है जो "सही लगता है" श्रेणी से संबंधित हैं लेकिन वास्तव में पूरी तरह से उपयोगी कुछ भी नहीं प्राप्त करते हैं (और कभी-कभी नकारात्मक परिणाम भी होते हैं)।

कथित तौर पर, एक सूचक को सेट करने के NULLबाद freeमाना जाता है कि "डबल फ्री" समस्या को रोकने के लिए जब एक ही पॉइंटर मान को freeएक से अधिक बार पास किया जाए। वास्तविकता में, 10 में से 9 मामलों में वास्तविक "डबल फ्री" समस्या तब होती है जब एक ही पॉइंटर मान रखने वाले विभिन्न पॉइंटर ऑब्जेक्ट्स को तर्क के रूप में उपयोग किया जाता है free। कहने की जरूरत नहीं है, इस तरह के मामलों में समस्या को रोकने के लिए पूरी तरह से कुछ भी हासिल करने के लिए एक संकेतक सेट करने के NULLबाद free

बेशक, तर्क के रूप में एक ही पॉइंटर ऑब्जेक्ट का उपयोग करते समय "डबल फ्री" समस्या में चलना संभव है free। हालांकि, इस तरह की वास्तविकता स्थितियों में आम तौर पर कोड की सामान्य तार्किक संरचना के साथ एक समस्या का संकेत मिलता है, न कि केवल आकस्मिक "डबल फ्री"। इस तरह के मामलों में समस्या से निपटने का एक उचित तरीका है कि एक ही पॉइंटर को freeएक से अधिक बार पास करने की स्थिति से बचने के लिए कोड की संरचना की समीक्षा और पुनर्विचार करना । ऐसे मामलों में NULL"निर्धारित" समस्या पर और उस पर विचार करने के लिए सूचक को सेट करना कालीन के नीचे समस्या को स्वीप करने के प्रयास से ज्यादा कुछ नहीं है। यह केवल सामान्य स्थिति में काम नहीं करेगा, क्योंकि कोड संरचना के साथ समस्या हमेशा खुद को प्रकट करने का एक और तरीका ढूंढेगी।

अंत में, यदि आपका कोड विशेष रूप से पॉइंटर मान के होने NULLया न होने पर भरोसा करने के लिए डिज़ाइन किया गया है NULL, तो पॉइंटर मान को NULLबाद में सेट करना पूरी तरह से ठीक है free। लेकिन एक सामान्य "अच्छा अभ्यास" नियम के रूप में (जैसा कि "हमेशा अपने सूचक को NULLबाद में सेट करें free") यह है, एक बार फिर, एक प्रसिद्ध और बहुत बेकार नकली, अक्सर विशुद्ध रूप से धार्मिक, वूडू जैसे कारणों के लिए कुछ द्वारा पीछा किया जाता है।


1
निश्चित रूप से। मुझे याद नहीं है कि कभी ऐसा डबल-फ्री होने का कारण हो, जो कि पॉइलर को फ्री करने के बाद पॉइंटर को सेट करके तय किया जाएगा, लेकिन मैंने बहुत कुछ किया है।
LnxPrgr3

4
@AnT "संदिग्ध" थोड़ा ज्यादा है। यह सब उपयोग के मामले पर निर्भर करता है। यदि पॉइंटर का मान कभी भी सही / गलत अर्थ में उपयोग किया जाता है, तो यह न केवल एक मान्य अभ्यास है, बल्कि यह एक सर्वोत्तम अभ्यास है।
कोडर

1
@ कोडर पूरी तरह से गलत। यदि पॉइंटर के मूल्य का उपयोग सच्चे झूठे अर्थ में यह जानने के लिए किया जाता है कि कॉल मुक्त करने से पहले किसी ऑब्जेक्ट को इंगित किया गया है या नहीं, तो यह न केवल सबसे अच्छा अभ्यास है, यह गलत है । उदाहरण के लिए foo* bar=getFoo(); /*more_code*/ free(bar); /*more_code*/ return bar != NULL;:। यहां, कॉल barकरने के NULLबाद सेटिंग करने freeसे फ़ंक्शन को लगता है कि यह कभी भी बार नहीं था और गलत मान लौटाएगा!
डेविड श्वार्ट्ज

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

1
मैं मानता हूं कि अच्छी तरह से संरचित कोड को उस मामले की अनुमति नहीं देनी चाहिए जहां एक सूचक को मुक्त होने के बाद पहुँचा जा सकता है या उस मामले में जहां इसे दो बार मुक्त किया गया है। लेकिन वास्तविक दुनिया में मेरे कोड को संशोधित और / या किसी ऐसे व्यक्ति द्वारा किया जाएगा जो शायद मुझे नहीं जानता है और चीजों को ठीक से करने के लिए समय और / या कौशल नहीं है (क्योंकि समय सीमा हमेशा कल होती है)। इसलिए मैं बुलेटप्रूफ फ़ंक्शंस लिखना पसंद करता हूं जो सिस्टम का दुरुपयोग न करने पर भी क्रैश न करें।
mfloris

34

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

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


1
+1 यह वास्तव में एक बहुत अच्छा बिंदु है। "डबल फ्री" (जो पूरी तरह से फर्जी है) के बारे में तर्क नहीं, लेकिन यह । मैं बाद में संकेत के यांत्रिक नल-आईएनजी का प्रशंसक नहीं हूं free, लेकिन यह वास्तव में समझ में आता है।
चींटी

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

1
@DavidSchwartz: मैं आपकी टिप्पणी से असहमत हूं। जब मुझे कुछ सप्ताह पहले एक विश्वविद्यालय अभ्यास के लिए एक स्टैक लिखना पड़ा, तो मुझे एक समस्या हुई, मैंने कुछ घंटों की जांच की। मैंने कुछ बिंदु पर पहले से ही कुछ फ्री होल्ड मेमोरी एक्सेस कर ली है (फ्री में कुछ लाइनें बहुत जल्दी थीं)। और कभी-कभी यह बहुत अजीब व्यवहार करता है। अगर मैं सूचक को मुक्त करने के बाद NULL को सेट करता, तो "सरल" सेगफॉल्ट होता और मैं कुछ घंटों के काम को बचा लेता। तो इस जवाब के लिए +1!
मेज़बोज़

2
@katze_sonne यहां तक ​​कि एक रुकी हुई घड़ी दिन में दो बार सही है। यह बहुत अधिक संभावना है कि NULL के लिए पॉइंटर्स सेट करना बग को छिपा देगा ताकि गलत तरीके से पहुंच को रोकने के लिए पहले से ही वस्तुओं को कोड में segfaulting से मुक्त किया जा सके जो NULL के लिए जाँच करता है और फिर चुपचाप किसी वस्तु की जाँच करने में विफल रहता है जिसे उसे जाँचना चाहिए था। (शायद विशिष्ट डीबग बिल्ड में मुफ्त के बाद NULL को पॉइंटर्स सेट करना सहायक हो सकता है, या उन्हें NULL के अलावा किसी अन्य मान पर सेट करना जो segfault की गारंटी है, समझ में आ सकता है। लेकिन यह एक बार आपके पक्ष में एक तर्क नहीं है , लेकिन यह मदद करने के लिए हुआ। ।)
डेविड श्वार्ट्ज

@DavidSchwartz खैर, यह उचित लगता है ... आपकी टिप्पणी के लिए धन्यवाद, मैं भविष्य में इस पर विचार करूंगा! :) +1
मौज़ूज़

20

ओवर राइटिंग मेमोरी से बचने के लिए यह अच्छा अभ्यास माना जाता है। उपरोक्त फ़ंक्शन में, यह अनावश्यक है, लेकिन अक्सर जब यह किया जाता है तो यह एप्लिकेशन त्रुटियों को पा सकता है।

इसके बजाय कुछ इस तरह आज़माएँ:

#if DEBUG_VERSION
void myfree(void **ptr)
{
    free(*ptr);
    *ptr = NULL;
}
#else
#define myfree(p) do { void ** __p = (p); free(*(__p)); *(__p) = NULL; } while (0)
#endif

DEBUG_VERSION आपको प्रोफ़ाइल को डीबगिंग कोड में मुक्त करने देता है, लेकिन दोनों कार्यात्मक रूप से समान हैं।

संपादित करें : जोड़ा गया ... नीचे दिए गए सुझाव के अनुसार, धन्यवाद।


3
यदि आप ब्रैकेट के बिना स्टेटमेंट के बाद इसका उपयोग करते हैं तो मैक्रो संस्करण में एक सूक्ष्म बग है।
मार्क रैनसम

(शून्य) 0 के साथ क्या है? यह कोड करते हैं: if (x) myfree (& x); और do_foo (); हो जाता है अगर (x) {free (* (x)); * (x) = null; } शून्य 0; और do_foo (); दूसरा एक त्रुटि है।
jmucchiello

वह मैक्रो अल्पविराम ऑपरेटर के लिए एक आदर्श स्थान है: मुफ्त ( (पी)), * (पी) = शून्य। बेशक अगली समस्या यह है कि इसका मूल्यांकन * (p) दो बार होता है। यह {void * _pp = (p) होना चाहिए ; मुफ्त पी & पी); * _प = अशक्त; } प्रीप्रोसेसर मजा नहीं है।
jmucchiello

5
मैक्रो नंगे कोष्ठक में नहीं होना चाहिए, यह एक do { } while(0)ब्लॉक में होना चाहिए ताकि if(x) myfree(x); else dostuff();टूट न जाए ।
क्रिस लुत्ज

3
जैसा कि लुत्ज़ ने कहा, मैक्रो बॉडी do {X} while (0)एक मैक्रो बॉडी बनाने का सबसे अच्छा तरीका है जो "एक फंक्शन की तरह लगता है और काम करता है"। अधिकांश संकलक वैसे भी लूप का अनुकूलन करते हैं।
माइक क्लार्क

7

यदि आप ऐसे संकेतक तक पहुंचते हैं जो मुक्त हो गया है () डी, तो यह टूट सकता है या नहीं। हो सकता है कि आपके प्रोग्राम के दूसरे हिस्से में यह मेमोरी फिर से आ जाए और आपको मेमोरी करप्शन मिल जाए,

यदि आप सूचक को NULL पर सेट करते हैं, तो यदि आप इसे एक्सेस करते हैं, तो प्रोग्राम हमेशा सेगफॉल्ट के साथ क्रैश होता है। और नहीं, कभी-कभी यह काम करता है '', और नहीं, अप्रत्याशित तरीके से दुर्घटनाग्रस्त हो जाता है ''। यह डिबग करना आसान है।


5
प्रोग्राम हमेशा सेगफ़ॉल्ट के साथ क्रैश नहीं होता है। यदि आप पॉइंटर का उपयोग करते हैं, तो इसका मतलब है कि डेरीफेरिंग से पहले एक बड़ी पर्याप्त ऑफसेट को लागू किया जाता है, तो यह पता योग्य मेमोरी तक पहुंच सकता है: ((MyHugeStruct *) 0) -> fieldNearTheEnd। और इससे पहले कि आप हार्डवेयर के साथ सौदा करते हैं जो 0 तक पहुँच को बिल्कुल भी नहीं रोकता है। हालाँकि, प्रोग्राम के सेगफ़ॉल्ट के साथ क्रैश होने की अधिक संभावना है।
स्टीव जेसप

7

सूचक को free'डी मेमोरी' पर सेट करने का मतलब है कि सूचक के माध्यम से उस मेमोरी को एक्सेस करने का कोई भी प्रयास अपरिहार्य व्यवहार के बजाय तुरंत दुर्घटनाग्रस्त हो जाएगा। इससे यह निर्धारित करना बहुत आसान हो जाता है कि चीजें कहां गलत हुईं।

मैं आपका तर्क देख सकता हूं: चूंकि nPtrइसके बाद गुंजाइश खत्म हो रही है nPtr = NULL, इसलिए इसे सेट करने का कोई कारण नहीं लगता है NULL। हालांकि, structसदस्य के मामले में या कहीं और जहां सूचक तुरंत दायरे से बाहर नहीं जा रहा है, यह अधिक समझ में आता है। यह तुरंत स्पष्ट नहीं है कि कोड द्वारा पुन: उपयोग किया जा सकता है या नहीं, इसका उपयोग नहीं किया जाना चाहिए।

यह संभावना है कि नियम इन दो मामलों के बीच अंतर किए बिना कहा जाता है, क्योंकि यह नियम को स्वचालित रूप से लागू करना अधिक कठिन है, डेवलपर्स को इसका पालन करने के लिए अकेले जाने दें। यह NULLहर मुफ्त के बाद संकेत सेट करने के लिए चोट नहीं करता है , लेकिन इसमें बड़ी समस्याओं को इंगित करने की क्षमता है।


7

सी में सबसे आम बग डबल फ्री है। मूल रूप से आप ऐसा कुछ करते हैं

free(foobar);
/* lot of code */
free(foobar);

और यह बहुत बुरा है, ओएस कुछ पहले से मुक्त मेमोरी को मुक्त करने की कोशिश करता है और आम तौर पर यह segfault। तो अच्छा अभ्यास करने के लिए सेट है NULL, तो आप परीक्षण और जाँच कर सकते हैं कि क्या आपको वास्तव में इस मेमोरी को मुक्त करने की आवश्यकता है

if(foobar != null){
  free(foobar);
}

यह भी ध्यान दिया जाना चाहिए कि free(NULL)ऐसा कुछ भी नहीं होगा जिससे आपको इफ स्टेटमेंट लिखना न पड़े। मैं वास्तव में एक ओएस गुरु नहीं हूं, लेकिन मैं बहुत सुंदर हूं यहां तक ​​कि ज्यादातर ओएस डबल फ्री पर दुर्घटनाग्रस्त हो जाएंगे।

यह भी एक मुख्य कारण है कि कचरा संग्रह (जावा, डॉटनेट) के साथ सभी भाषाओं को इस समस्या के न होने पर बहुत गर्व था और साथ ही संपूर्ण रूप से स्मृति प्रबंधन के लिए डेवलपर्स को नहीं छोड़ना पड़ा।


11
आप वास्तव में सिर्फ मुफ्त कॉल कर सकते हैं () जाँच के बिना - मुफ्त (NULL) को कुछ भी नहीं करने के रूप में परिभाषित किया गया है।
अंबर

5
कि कीड़े छिपा नहीं है? (बहुत अधिक मुक्त करने की तरह।)
जॉर्ज शॉर्ली

1
thanx, मैं समझ गया। मैंने कोशिश की:p = (char *)malloc(.....); free(p); if(p!=null) //p!=null is true, p is not null although freed { free(p); //Note: checking doesnot prevent error here }
शाओबो वांग

5
जैसा कि मैंने कहा, पॉइंटर के मूल्य को बदल free(void *ptr) नहीं सकता है। यह पॉइंटर की सामग्री , उस पते पर संग्रहीत डेटा को बदल सकता है , लेकिन खुद पते को नहीं , या पॉइंटर के मूल्य को । इसके लिए आवश्यकता होगी free(void **ptr)(जो स्पष्ट रूप से मानक द्वारा अनुमत नहीं है) या एक मैक्रो (जो अनुमत है और पूरी तरह से पोर्टेबल है लेकिन लोग मैक्रोज़ को पसंद नहीं करते हैं)। इसके अलावा, सी सुविधा के बारे में नहीं है, यह प्रोग्रामर को उतना नियंत्रण देने के बारे में है जितना वे चाहते हैं। यदि वे पॉइंटर्स को सेट करने के अतिरिक्त ओवरहेड नहीं चाहते हैं NULL, तो यह उन पर मजबूर नहीं होना चाहिए।
क्रिस लुट्ज़

2
दुनिया में कुछ चीजें हैं जो सी कोड लेखक की ओर से व्यावसायिकता की कमी को दूर करती हैं। लेकिन उनमें "कॉल करने से पहले NULL के लिए पॉइंटर की जाँच करना free" ("मेमोरी एलोकेशन फ़ंक्शंस के परिणाम को कास्टिंग करना" या "" के साथ प्रकार के नामों का उपयोग न करना sizeof) जैसी चीज़ें शामिल हैं ।
एनटी

6

इसके पीछे विचार, मुक्त किए गए पॉइंटर के आकस्मिक पुन: उपयोग को रोकना है।


4

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

यदि आप पॉइंटर को बाहर निकालते हैं, तो इसका उपयोग करने का कोई भी प्रयास 0x0 पर होने वाला है और वहीं क्रैश हो जाता है, जिसे डीबग करना आसान है। रैंडम पॉइंटर्स जो रैंडम मेमोरी की ओर इशारा करते हैं, डिबग करना कठिन है। यह स्पष्ट रूप से आवश्यक नहीं है लेकिन फिर भी यह एक सर्वोत्तम अभ्यास दस्तावेज में क्यों है।


विंडोज पर, कम से कम, डिबग बिल्ड मेमोरी को 0xdddddddd पर सेट करेगा जब आप तुरंत हटाए गए मेमोरी के लिए एक पॉइंटर का उपयोग करते हैं जो आप जानते हैं। सभी प्लेटफार्मों पर समान तंत्र होना चाहिए।
इ_म_जॉर्फ

2
jeffamaphone, हटाए गए मेमोरी ब्लॉक को पुनः प्राप्त करने और किसी अन्य ऑब्जेक्ट को तब तक असाइन किया जा सकता है जब तक आप पुन: पॉइंटर का उपयोग करते हैं।
कॉन्सटेंटिन

4

ANSI C मानक से:

void free(void *ptr);

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

"अपरिभाषित व्यवहार" लगभग हमेशा एक कार्यक्रम दुर्घटना है। इसलिए इससे बचने के लिए पॉइंटर को NULL में रीसेट करना सुरक्षित है। free () स्वयं ऐसा नहीं कर सकता क्योंकि यह केवल एक सूचक को दिया जाता है, एक सूचक को सूचक नहीं। आप फ्री का सुरक्षित संस्करण भी लिख सकते हैं () जो सूचक को पूरा करता है:

void safe_free(void** ptr)
{
  free(*ptr);
  *ptr = NULL;
}

@DrPizza - एक त्रुटि (मेरी राय में) कुछ ऐसा है जो आपके प्रोग्राम को काम नहीं करने का कारण बनता है जैसा कि यह माना जाता है। यदि एक छिपी हुई डबल फ्री आपके प्रोग्राम को तोड़ देती है, तो यह एक त्रुटि है। यदि यह ठीक उसी तरह से काम करता है जैसा कि इसका इरादा था, तो यह कोई त्रुटि नहीं है।
क्रिस लुत्ज़

@DrPizza: मुझे सिर्फ एक तर्क मिला है कि किसी को NULLमास्किंग त्रुटियों से बचने के लिए इसे क्यों सेट करना चाहिए । stackoverflow.com/questions/1025589/… ऐसा लगता है कि या तो मामले में कुछ त्रुटियां छिपी हुई हैं।
जॉर्ज शॉर्ली

1
ज्ञात हो कि एक शून्य पॉइंटर-टू-पॉइंटर की अपनी समस्याएं हैं: c-faq.com/ptrs/genericpp.html
सुरक्षित

3
@ क्रिस, नहीं, सबसे अच्छा तरीका कोड संरचना है। रैंडम माल्क्स को न फेंकें और अपने कोडबेस से सभी को मुक्त करें, संबंधित चीजों को एक साथ रखें। "मॉड्यूल" जो एक संसाधन आवंटित करता है (मेमोरी, फ़ाइल, ...) इसे मुक्त करने के लिए ज़िम्मेदार है और ऐसा करने के लिए एक फ़ंक्शन प्रदान करना है जो पॉइंटर्स की देखभाल भी करता है। किसी भी विशिष्ट संसाधन के लिए, आपके पास वास्तव में एक जगह होती है, जहां इसे आवंटित किया जाता है और एक जगह जहां इसे छोड़ा जाता है, दोनों एक साथ बंद हो जाते हैं।
सुरक्षित रखें

4
@ क्रिस लुत्ज़: हॉगवॉश। यदि आप एक ही पॉइंटर को दो बार मुक्त करने वाले कोड लिखते हैं, तो आपके प्रोग्राम में तार्किक त्रुटि है। उस तार्किक त्रुटि को दुर्घटनाग्रस्त न करने से यह मतलब नहीं है कि कार्यक्रम सही है: यह अभी भी कुछ निरर्थक है। ऐसा कोई परिदृश्य नहीं है जिसमें डबल फ्री लिखना उचित हो।
DrPizza

4

मुझे लगता है कि यह मेरे अनुभव के रूप में बहुत कम मदद करता है जब लोग एक मुक्त स्मृति आवंटन का उपयोग करते हैं, यह लगभग हमेशा होता है क्योंकि उनके पास कहीं और इसका संकेत होता है। और फिर यह एक और व्यक्तिगत कोडिंग मानक के साथ संघर्ष करता है जो "बेकार अव्यवस्था से बचें" है, इसलिए मैं ऐसा नहीं करता क्योंकि मुझे लगता है कि यह शायद ही कभी मदद करता है और कोड को थोड़ा कम पठनीय बनाता है।

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

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

एक सामान्य पैटर्न यह है कि कंस्ट्रक्टर में NULL के सभी सदस्य बिंदुओं को सेट करें और किसी भी पॉइंटर्स पर डिस्ट्रक्टर कॉल डिलीट करने के लिए डेटा है कि आपका डिज़ाइन कहता है कि क्लास का मालिक है । स्पष्ट रूप से इस मामले में आपको सूचक को NULL में सेट करना होगा जब आप कुछ हटाने के लिए यह इंगित करें कि आपके पास पहले कोई डेटा नहीं है।

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


4

हाल ही में मैं उसी प्रश्न के उत्तर में आया हूं जब मैं उत्तर की तलाश में था। मैं इस निष्कर्ष पर पहुँचा:

यह सबसे अच्छा अभ्यास है, और इसे सभी (एम्बेडेड) सिस्टम पर पोर्टेबल बनाने के लिए इसका पालन करना चाहिए।

free()एक लाइब्रेरी फ़ंक्शन है, जो एक प्लेटफ़ॉर्म को बदलता है, इसलिए आपको यह अपेक्षा नहीं करनी चाहिए कि इस फ़ंक्शन को पॉइंटर पास करने के बाद और मेमोरी को फ़्री करने के बाद, यह पॉइंटर NULL पर सेट हो जाएगा। प्लेटफ़ॉर्म के लिए लागू कुछ लाइब्रेरी के लिए ऐसा नहीं हो सकता है।

तो हमेशा के लिए जाओ

free(ptr);
ptr = NULL;

3

यह नियम तब उपयोगी है जब आप निम्नलिखित परिदृश्य से बचने की कोशिश कर रहे हों:

1) आपके पास जटिल तर्क और स्मृति प्रबंधन के साथ एक बहुत लंबा कार्य है और आप गलती से बाद में फ़ंक्शन में हटाए गए मेमोरी को पॉइंटर का पुन: उपयोग नहीं करना चाहते हैं।

2) सूचक एक वर्ग का सदस्य चर है जिसका व्यवहार काफी जटिल है और आप गलती से अन्य कार्यों में मेमोरी को हटाने के लिए सूचक का पुन: उपयोग नहीं करना चाहते हैं।

आपके परिदृश्य में, यह पूरी तरह से समझ में नहीं आता है, लेकिन यदि फ़ंक्शन लंबे समय तक प्राप्त करना था, तो यह मामला हो सकता है।

आप यह तर्क दे सकते हैं कि इसे NULL पर सेट करना वास्तव में बाद में तर्क त्रुटियों को मास्क कर सकता है, या जिस स्थिति में आप इसे मान्य मानते हैं, आप अभी भी NULL पर क्रैश करते हैं, इसलिए यह कोई फर्क नहीं पड़ता।

सामान्य तौर पर, मैं आपको सलाह दूंगा कि जब आप सोचते हैं कि यह एक अच्छा विचार है, तो इसे NULL पर सेट करें और जब आपको लगता है कि यह इसके लायक नहीं है तो परेशान न हों। लघु फ़ंक्शंस और अच्छी तरह से डिज़ाइन की गई कक्षाओं को लिखने के बजाय फ़ोकस करें।


2

दूसरे ने जो कहा है, उसे जोड़ने के लिए, सूचक उपयोग की एक अच्छी विधि हमेशा यह जांचने के लिए है कि यह वैध सूचक है या नहीं। कुछ इस तरह:


if(ptr)
   ptr->CallSomeMethod();

स्पष्ट रूप से सूचक को खाली करने के बाद NULL के रूप में चिह्नित करना C / C ++ में इस तरह के उपयोग की अनुमति देता है।


5
कई मामलों में, जहां एक NULL पॉइंटर का कोई मतलब नहीं है, इसके बजाय एक मुखर लिखना बेहतर होगा।
एरिच किट्ज़म्यूलर

2

यह सभी संकेत को NULL को आरंभ करने के लिए अधिक तर्क हो सकता है, लेकिन कुछ इस तरह से एक बहुत ही डरावना बग हो सकता है:

void other_func() {
  int *p; // forgot to initialize
  // some unrelated mallocs and stuff
  // ...
  if (p) {
    *p = 1; // hm...
  }
}

void caller() {
  some_func();
  other_func();
}

pपूर्व की तरह स्टैक पर एक ही स्थान पर समाप्त होता है nPtr, इसलिए इसमें अभी भी एक उचित वैध सूचक हो सकता है। *pसभी प्रकार की असंबंधित चीजों को अधिलेखित करने और बदसूरत कीड़े को जन्म देने के लिए असाइन करना । खासकर यदि कंपाइलर डिबग मोड में शून्य के साथ स्थानीय चर को इनिशियलाइज़ करता है लेकिन एक बार ऑप्टिमाइज़ेशन चालू नहीं होता है। तो डिबग बनाता है बग के किसी भी लक्षण नहीं दिखाते हैं जबकि रिलीज बिल्ड बेतरतीब ढंग से उड़ा ...


2

पॉइंटर को सेट करें जिसे केवल NULL से मुक्त किया गया है अनिवार्य नहीं है लेकिन एक अच्छा अभ्यास है। इस तरह, आप एक मुक्त अंक 2 का उपयोग करके 1) से बच सकते हैं) इसे तीन बार मुक्त कर सकते हैं


2

NULL के लिए एक पॉइंटर की सेटिंग फिर से तथाकथित डबल-फ्री की रक्षा करने के लिए है - एक ऐसी स्थिति जब मुफ्त () उस पते पर ब्लॉक को पुनः प्राप्त किए बिना एक ही पते के लिए एक से अधिक बार कहा जाता है।

डबल-फ्री अपरिभाषित व्यवहार की ओर जाता है - आमतौर पर भ्रष्टाचार को ढेर करता है या कार्यक्रम को तुरंत दुर्घटनाग्रस्त करता है। NULL पॉइंटर के लिए फ्री () कॉलिंग कुछ नहीं करती है और इसलिए सुरक्षित रहने की गारंटी है।

इसलिए सबसे अच्छा अभ्यास जब तक आप यह सुनिश्चित नहीं कर लेते हैं कि सूचक मुक्त होने के तुरंत बाद या बहुत जल्द ही गुंजाइश छोड़ देता है (तो उस सूचक को NULL पर सेट करना है ताकि मुक्त होने पर भी) उसे अब NULL सूचक और अपरिभाषित व्यवहार कहा जाए विकसित किया गया है।


2

विचार यह है कि यदि आप इसे मुक्त करने के बाद नो-लॉन्ग-वैलिड पॉइंटर को निष्क्रिय करने की कोशिश करते हैं, तो आप चुपचाप और रहस्यमय तरीके से नहीं बल्कि कठिन (सेगफॉल्ट) को विफल करना चाहते हैं।

लेकिन सावधान रहना। यदि आपके पास NULL की अवहेलना नहीं है, तो सभी सिस्टम एक segfault का कारण बनते हैं। पर (कम से कम कुछ संस्करण) AIX, * (int *) 0 == 0, और Solaris में इस AIX "सुविधा के साथ वैकल्पिक संगतता है।"


2

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

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

माप की समस्या यह है कि जब भी आप कम से अच्छे को विभाजित करने का प्रयास करते हैं, तो मामला जितना जटिल होता है, उतनी ही अधिक संभावना आपको अस्पष्ट माप से मिलती है। यदि लक्ष्य है, केवल अच्छी प्रथाओं को बनाए रखें, तो कुछ अस्पष्ट लोग वास्तव में अच्छे नहीं हैं। यदि आपका लक्ष्य अच्छा नहीं है, तो अस्पष्टता अच्छे के साथ रह सकती है। दो लक्ष्य, केवल अच्छा रखें या स्पष्ट रूप से खराब को खत्म करें, ऐसा प्रतीत होता है कि इसका विरोध किया जा रहा है, लेकिन आमतौर पर एक तीसरा समूह होता है जो न तो एक होता है और न ही दोनों।

गुणवत्ता विभाग के साथ मामला करने से पहले, बग डेटा बेस के माध्यम से देखने का प्रयास करें कि कितनी बार, यदि कभी, अमान्य पॉइंटर मानों के कारण समस्याएँ हुईं, जिन्हें लिखना पड़ा। यदि आप वास्तविक अंतर बनाना चाहते हैं, तो अपने उत्पादन कोड में सबसे आम समस्या की पहचान करें और इसे रोकने के तीन तरीकों का प्रस्ताव करें


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

2

इसके दो कारण हैं:

डबल-फ्री होने पर क्रैश से बचें

डुप्लिकेट प्रश्न में रेजेज द्वारा लिखित ।

सी में सबसे आम बग डबल फ्री है। मूल रूप से आप ऐसा कुछ करते हैं

free(foobar);
/* lot of code */
free(foobar);

और यह बहुत बुरा है, ओएस कुछ पहले से मुक्त मेमोरी को मुक्त करने की कोशिश करता है और आम तौर पर यह segfault। तो अच्छा अभ्यास करने के लिए सेट है NULL, तो आप परीक्षण और जाँच कर सकते हैं कि क्या आपको वास्तव में इस मेमोरी को मुक्त करने की आवश्यकता है

if(foobar != NULL){
  free(foobar);
}

यह भी ध्यान दिया जाना चाहिए कि free(NULL) ऐसा कुछ भी नहीं होगा जिससे आपको इफ स्टेटमेंट लिखना न पड़े। मैं वास्तव में एक ओएस गुरु नहीं हूं, लेकिन मैं बहुत सुंदर हूं यहां तक ​​कि ज्यादातर ओएस डबल फ्री पर दुर्घटनाग्रस्त हो जाएंगे।

यह भी एक मुख्य कारण है कि कचरा संग्रह (जावा, डॉटनेट) के साथ सभी भाषाओं को इस समस्या के नहीं होने पर गर्व था और समग्र रूप से मेमोरी प्रबंधन को छोड़ने के लिए भी नहीं था।

पहले से ही मुक्त संकेत का उपयोग करने से बचें

एक अन्य उत्तर में मार्टिन वी। लोविस द्वारा लिखित ।

अप्रयुक्त बिंदुओं को NULL पर सेट करना एक रक्षात्मक शैली है, जो कि पॉइंटर पॉइंटर बग्स से बचाता है। यदि एक झूलने वाला सूचक मुक्त होने के बाद एक्सेस किया जाता है, तो आप यादृच्छिक मेमोरी को पढ़ या अधिलेखित कर सकते हैं। यदि कोई नल पॉइंटर एक्सेस किया गया है, तो आपको अधिकांश सिस्टम पर तत्काल दुर्घटना मिलती है, जो आपको बताती है कि त्रुटि क्या है।

स्थानीय चर के लिए, यह थोड़ा स्पष्ट हो सकता है यदि यह "स्पष्ट" है कि सूचक मुक्त होने के बाद अब तक पहुँचा नहीं है, इसलिए यह शैली सदस्य डेटा और वैश्विक चर के लिए अधिक उपयुक्त है। स्थानीय चर के लिए भी, यह एक अच्छा तरीका हो सकता है यदि मेमोरी जारी होने के बाद फ़ंक्शन जारी रहता है।

शैली को पूरा करने के लिए, आपको पॉइंटर्स को इनिशियलाइज़ करना चाहिए, इससे पहले कि वे एक सच्चे पॉइंटर वैल्यू असाइन करें।


1

जैसा कि आपके पास गुणवत्ता आश्वासन टीम है, मुझे क्यूए के बारे में एक मामूली बात जोड़ने दें। C के लिए कुछ स्वचालित QA उपकरण "निरर्थक असाइनमेंट" के रूप में मुक्त किए गए पॉइंटर्स को असाइन करेंगे ptr। उदाहरण के लिए जिम्पेल सॉफ्टवेयर के पीसी-लिंट / फ्लेक्सलिंट कहते हैं tst.c 8 Warning 438: Last value assigned to variable 'nPtr' (defined at line 5) not used

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


1

यह हमेशा सलाह दी जाती है कि NULL के साथ पॉइंटर वैरिएबल घोषित करें ,

int *ptr = NULL;

बता दें, ptr 0x1000 मैमोरी एड्रेस की ओर इशारा कर रहा है । उपयोग करने के बाद free(ptr), हमेशा NULL को फिर से घोषित करके पॉइंटर वैरिएबल को शून्य करना उचित है । उदाहरण के लिए:

free(ptr);
ptr = NULL;

नहीं फिर से घोषित तो शून्य , सूचक चर अभी भी एक ही पते (की ओर इशारा करते रहती है 0x1000 ), इस सूचक चर एक कहा जाता है झूलते सूचक । यदि आप दूसरे पॉइंटर वेरिएबल को परिभाषित करते हैं ( मान लें, क्ष ) और डायनामिक रूप से नए पॉइंटर को एड्रेस आवंटित करते हैं, तो नए पॉइंटर वेरिएबल द्वारा एक ही एड्रेस ( 0x1000 ) लेने का मौका है । मामले में, आप एक ही सूचक (का उपयोग करते हैं ptr ) और मान को अद्यतन पते पर एक ही सूचक (द्वारा बताया ptr ), तो कार्यक्रम जगह है जहाँ के लिए एक मूल्य लेखन खत्म हो जाएगा क्ष (इशारा कर रही है के बाद से पी और क्यू हैं उसी पते की ओर इशारा करते हुए (0x1000 )) है।

जैसे

*ptr = 20; //Points to 0x1000
free(ptr);
int *q = (int *)malloc(sizeof(int) * 2); //Points to 0x1000
*ptr = 30; //Since ptr and q are pointing to the same address, so the value of the address to which q is pointing would also change.

1

लंबी कहानी छोटी: आप गलती से (उस गलती से) उस पते तक नहीं पहुँचना चाहते जिसे आपने मुक्त किया है। क्योंकि, जब आप पते को मुक्त कर देते हैं, तो आप उस पते को ढेर में किसी अन्य अनुप्रयोग को आवंटित करने की अनुमति देते हैं।

हालाँकि, यदि आपने पॉइंटर को NULL पर सेट नहीं किया है, और गलती से पॉइंटर को डी-रेफर करने की कोशिश करते हैं, या उस एड्रेस का मान बदल देते हैं; आप इसे अभी भी कर सकते हैं। लेकिन यह मत करो कि तुम क्या करना चाहते हो तार्किक रूप से।

मैं अभी भी उस स्मृति स्थान तक क्यों पहुंच सकता हूं जिसे मैंने मुक्त किया है? क्योंकि: आपके पास मेमोरी खाली हो सकती है, लेकिन पॉइंटर चर में अभी भी ढेर मेमोरी एड्रेस के बारे में जानकारी थी। इसलिए, एक रक्षात्मक रणनीति के रूप में, इसे NULL पर सेट करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.