2013-02-13 8 views
5

शीर्षक यह सब कहता है।जब कोई पॉइंटर स्कोप में बनाया जाता है, तो पॉइंटर गुंजाइश से बाहर होने पर चर के लिए क्या होता है?

I found an old question that is essentially the same, लेकिन मुझे थोड़ा और स्पष्टीकरण की आवश्यकता थी।

इस सवाल में स्वीकार किए जाते हैं जवाब का कहना है:

char* text = "Hello, world"; 

यहाँ एक स्वत: चर (एक सूचक) ढेर पर बनाया गया है और लगातार स्मृति में एक मूल्य को इंगित करने के लिए सेट, है जिसका अर्थ है:

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

इस कह रही है कि सूचक को नष्ट कर दिया जाता है, लेकिन नहीं डेटा सूचक की ओर इशारा करते है? यदि मैं किसी फ़ंक्शन में वर्णों के लिए 1,000,000 पॉइंटर्स बनाना चाहता था, तो जब वे दायरे से बाहर निकलते हैं तो मेरी सभी यादें रिलीज़ हो जाएंगी? या सिर्फ पॉइंटर्स बनाने के लिए आवश्यक मेमोरी, वास्तविक पात्रों को अपने सभी मेमोरी को हॉग करने के लिए पीछे छोड़कर?

+0

सूचक ** ** ** हटाया नहीं जाता है। यह नष्ट हो जाता है, जो एक सूचक के मामले में कुछ भी नहीं करता है। –

उत्तर

8

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

पॉइंटर्स में स्वचालित संग्रहण अवधि होती है और जब वे दायरे से बाहर निकलते हैं तो नष्ट हो जाते हैं। यह ध्यान देने योग्य है कि सूचक को const char* होना चाहिए क्योंकि स्ट्रिंग अक्षर आपको const char की सरणी देता है। पर विचार करें:

void func() 
{ 
    const char* str = "Hello"; 
} 

युक्त Hello\0 अपने कार्यक्रम की अवधि के लिए मौजूद है पात्रों की सरणी। सूचक str केवल उस फ़ंक्शन की अवधि के लिए मौजूद है। यहां deleted होने की आवश्यकता नहीं है।

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

यदि आपके प्रोग्राम में दो स्ट्रिंग अक्षर हैं जिनके पास समान या ओवरलैपिंग टेक्स्ट है, तो कोई कारण नहीं है कि संकलक इसे केवल उनमें से एक को संग्रहीत करने में अनुकूलित नहीं कर सकता है। पर विचार करें:

void func() 
{ 
    const char* str1 = "Hello"; 
    const char* str2 = "Hello"; 
    const char* str3 = "lo"; 
} 

संकलक केवल एक बार यहाँ निष्पादन में पात्रों Hello\0 लिखने के लिए की जरूरत है। पहले दो पॉइंटर्स केवल H पर इंगित करेंगे और तीसरा दूसरा l इंगित करेगा। आपका कंपाइलर इस तरह अनुकूलन कर सकता है। बेशक, इस उदाहरण के साथ, कंपाइलर स्ट्रिंग्स को एक साथ छुटकारा पाने के द्वारा और भी अनुकूलन कर सकता है - इनका उपयोग किसी भी तरह से नहीं किया जाता है जो कार्यक्रम के देखने योग्य व्यवहार में योगदान देता है।

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

+0

तो मेरे प्रश्नों में से एक में अस्पष्टता (असली शब्द नहीं) काटना, मेरे पास एक ऐसा कार्य है जो एक सूचक 'हस्ताक्षर किए गए चार * imageData; ', जो बाद में किसी अन्य फ़ंक्शन में फेंक दिया जाता है, और डेटा के साथ संलग्न हो जाता है। जब मैं छविडेटा के साथ आवश्यक सभी परिचालनों को पूरा करने के बाद, यदि मैं इसे स्पष्ट रूप से हटा नहीं पाता हूं, तो पॉइंटर गुंजाइश से बाहर हो जाएगा और मुक्त हो जाएगा, लेकिन यह जिस डेटा को इंगित कर रहा था वह रहेगा? – xcdemon05

+0

यह इस बात पर निर्भर करता है कि स्मृति आवंटित कैसे किया गया था। ** स्ट्रिंग अक्षर ** ** स्थिर भंडारण अवधि * है। आप उन्हें 'हटा नहीं सकते'। इसका मतलब यह नहीं है कि जब पॉइंटर गुंजाइश से बाहर हो जाता है तो स्ट्रिंग अक्षरशः स्वचालित रूप से नष्ट हो जाता है - यह सिर्फ नष्ट नहीं होता है! हालांकि, अगर आप 'इमेजडेटा' को 'नए हस्ताक्षरित चार [100]' जैसे कुछ कर कर उस सरणी को आवंटित करते हैं, तो इस सरणी में * गतिशील संग्रहण अवधि * होनी चाहिए और इसे हटाएं [] 'd, अन्यथा आपके पास स्मृति रिसाव। सुनहरा नियम: ** केवल 'हटाएं'/'हटाएं [] 'आप क्या नया' /' नया [] '! ** –

+0

ठीक है जो समझ में आता है। धन्यवाद!! :) – xcdemon05

2

मैं "कुछ नहीं" (शीर्षक का जवाब देने के लिए) कहूंगा, अगर यह एसओ के लिए उत्तर देने के लिए पर्याप्त था।

आपके लाखों पॉइंटर्स के पात्रों के लिए, जबकि पॉइंटर्स पॉप हो जाएंगे (हालांकि आपको लाख पॉइंटर्स रखने के लिए काफी ढेर होना चाहिए) जो डेटा वे इंगित करते हैं, वे आपकी यादों को परेशान करेंगे।

+0

गोटा, इसलिए उन्हें हटाना एक जरूरी है। – xcdemon05

+0

@ xcdemon05 नहीं, नहीं, मुझे लगता है कि "आपकी यादों को हंट करें" माइकल का मतलब है "केवल आपकी यादों में ही मौजूद होगा।" – djechlin

+0

मुझे भ्रमित करना बंद करो! ;) – xcdemon05

1

पॉइंटर स्वयं "स्वचालित संग्रहण" (जो आम तौर पर ढेर होता है) पर स्थान पर कब्जा करता है। फ़ंक्शन लौटने के बाद इसे हटा दिया जाता है [या दायरा समाप्त हो जाता है, लेकिन तकनीकी रूप से, लगभग सभी कंपाइलर "प्रतीक्षा" करेंगे जब तक कि अंतरिक्ष मुक्त होने से पहले फ़ंक्शन वापस नहीं आ जाता]।

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

char *foo() 
{ 
    char *text1 = "Hello"; 
    return text1; 
} 

void bar() 
{ 
    char *text2 = "World!"; 
    printf("%s %s!\n", foo(), text2); 
} 


void baz() 
{ 
    char *text3 = "Meh"; 
    bar(); 
} 

int main() 
{ 
    char *text4 = "Main"; 

    baz(); 
} 

जब हम मुख्य प्रवेश करते हैं, text4 स्टैक पर बनाई गई है - यह स्ट्रिंग "मुख्य" जो स्मृति के कुछ अन्य बिट में आयोजित किया जाता है के लिए शुरू किया गया है। जब हम तो baz() फोन, text3 बनाया है और "मेह" है, जो bar() कि text2 और अंक बनाता पाठ "दुनिया" के लिए, और foo जो text1 और Hello को initalizes बनाता कॉल कॉल करने के लिए प्रारंभ हो जाता है। foo रिटर्न के रूप में, text1 के अंदर का पता वापसी मूल्य के रूप में दिया जाता है, और सूचक स्वयं ही चला जाता है। जब printf() समाप्त हो गया है, bar रिटर्न, और सूचक दूर हो जाता है।

स्ट्रिंग्स "मुख्य", "मेह", "हैलो" और "वर्ल्ड" तब तक चल रहे हैं जब तक कार्यक्रम चल रहा है।

1

आपका उदाहरण, दुर्भाग्य से, पूर्ण तस्वीर को संबोधित करने के लिए अपर्याप्त है।

सबसे पहले, कुछ सरल सहारा शब्दावली और स्पष्टीकरण: एक स्मृति सेल, एक (सी में टाइप ++) किसी दिए गए आकार के साथ स्मृति का क्षेत्र है यह एक मूल्य शामिल हैं। कई मेमोरी कोशिकाओं में समान मान हो सकते हैं, इससे कोई फर्क नहीं पड़ता।

वहाँ है कि आप पर विचार किया जाना चाहिए स्मृति कोशिकाओं के 3 प्रकार हैं:

  • "Hello, World!": इस स्मृति सेल स्थिर भंडारण अवधि है, यह कार्यक्रम
  • void foo(int a); और void foo() { int a = 5; } की अवधि के दौरान मौजूद है: मेमोरी सेल a, दोनों मामलों में, स्वचालित स्टोरेज अवधि है, यह गायब हो जाएगा जब एक बार फ़ंक्शन foo
  • void foo() { int* a = new 5; }: एक गुमनाम स्मृति सेल "कहीं" बनाई गई है मूल्य 5, और स्वत: भंडारण अवधि के साथ एक स्मृति सेल a स्टोर करने के लिए गुमनाम एक

तो की पता स्टोर करने के लिए बनाई गई है , क्या होता है जब पॉइंटर गुंजाइश से बाहर चला जाता है ( गायब हो जाता है)?

ठीक है, बस यही। सूचक गायब हो जाता है। सबसे विशेष रूप से, मेमोरी सेल पर विशेष कुछ भी नहीं होता है, यह इंगित कर रहा था।

void foo(int a) { 
    int* pointer = &a; 
} // pointer disappears, `a` still exists briefly 

void foo() { 
    int* pointer = 0; 
    { 
     int a; 
     pointer = &a; 
    } // a disappears, pointer's value does not change... 
} // pointer disappears 

दरअसल, C और C++ में:

  • आप वस्तुओं नहीं रह गया है =>मौजूद है झूलते संदर्भ के पते बनाए रख सकते हैं
  • आप किसी मौजूदा ऑब्जेक्ट के लिए सभी पतों खो सकते हैं = >स्मृति रिसाव

तो क्या होता है जब textchar const* text = "Hello, world"; में दायरे से बाहर हो जाता है?

कुछ भी नहीं।

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

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