2012-11-06 31 views
17

क्या कोई मेरी मदद कर सकता है, आवंटित स्मृति को मुक्त करने का प्रयास करते समय मुझे एक त्रुटि संदेश क्यों मिल रहा है: ढेर भ्रष्टाचार का पता चला। सीटीआर ने पाया कि एप्लिकेशन ने हीप बफर के अंत में स्मृति लिखा था।सी ++ नया/हटाएं और चार *

char *ff (char *s){ 
    char *s1 = new char [strlen(s)]; 
    strcpy(s1, s); 
    return s1; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    char *s = new char [5]; 

    strcpy(s, "hello"); 
    char *s2 = ff(s); 

    delete []s;  // This works normal 
    delete []s2; // But I get an error on that line 
    return 0; 
} 
+9

जाहिर है, यह सिर्फ एक व्यायाम और एक वास्तविक में है सेटिंग के बजाय आप 'std :: string' का उपयोग करेंगे, है ना? –

+0

@MatthieuM। बिल्कुल सही। मुझे std :: स्ट्रिंग का उपयोग करने की अनुमति नहीं है; – user1448906

उत्तर

41
char *s = new char [5]; 
strcpy(s, "hello"); 

कारण अपरिभाषित व्यवहार (यूबी)
आप आवंटित यादों की सीमाओं से परे लिख रहे हैं। आपने 5 वर्णों के लिए पर्याप्त मेमोरी आवंटित की है लेकिन आपकी स्ट्रिंग में 6 वर्ण हैं जिनमें \0 शामिल हैं।

एक बार आपके प्रोग्राम ने इस यूबी के कारण होने के बाद, सभी दांव बंद हैं और कोई भी व्यवहार संभव है।

आप की जरूरत है:

char *s = new char [strlen("hello") + 1]; 

वास्तव में आदर्श समाधान std::string और नहीं char * उपयोग करने के लिए है। ये गलतियों को सटीक हैं जो std::string avoids। और आपके उदाहरण में std::string के बजाय char * का उपयोग करने की कोई वास्तविक आवश्यकता नहीं है।
std::string के साथ:

  • आप new कुछ भी
  • की जरूरत नहीं है तुम, delete कुछ भी &
  • आप std::string के साथ सब कुछ कर सकते हैं की जरूरत नहीं है कि आप char * के साथ क्या।
+1

सहमत हैं कि 'std :: string' का उपयोग करना सबसे अच्छा तरीका है। आपके उत्तर के माध्यम से बेहतर 'नया' आवंटन मिडवे लिखने का एक अन्य तरीका 'char * s = new char [sizeof ("हैलो")] होगा,' रनटाइम पर 'strlen() 'पर कॉल से बचें (हालांकि एक स्मार्ट कंपाइलर संभवतः इसे अनुकूलित कर सकते हैं)। यह स्पष्ट रूप से केवल तभी काम करता है यदि आपके पास लगातार स्ट्रिंग है, हालांकि, जो शायद सामान्य मामला नहीं है। –

13

new char [strlen(s)];, समापन \0 चरित्र में नहीं गिना जाता तो अपने बफर एक वर्ण बहुत छोटा है।

9

strcpy में शून्य टर्मिनेटर शामिल है; strlen नहीं करता है। लिखें:

char *s1 = new char [strlen(s) + 1]; 
0

आपकी प्रारंभिक स्ट्रिंग s केवल पांच वर्ण लंबी है इसलिए इसे समाप्त नहीं किया जा सकता है। "hello" की प्रतिलिपि strcpy द्वारा प्रतिलिपि बनाई जाएगी, लेकिन आप बफर को ओवरराउन कर देंगे। strlen को इसे समाप्त कर दिया जाना चाहिए ताकि अगर नल वहां न हो, तो आपको समस्याएं हो सकती हैं। इस लाइन को बदलने का प्रयास करें:

char * s = new char [6];

बेहतर अभी भी, std::string सी शैली स्ट्रिंग फ़ंक्शंस को पसंद करें - वे उतने ही कुशल और उपयोग करने के लिए बहुत सुरक्षित और आसान हैं। साथ ही, new और delete से बचने का प्रयास करें जबतक कि आपको वास्तव में उनका उपयोग नहीं करना पड़े। आपको जो समस्याएं मिल रही हैं वे बहुत आम हैं और आसानी से बचा जा सकता है।

1

'\0' के लिए जगह बनाने के लिए आपको char *s1 = new char [strlen(s) + 1]; निर्दिष्ट करने की आवश्यकता है जो स्ट्रिंग को समाप्त करता है।

6
आदमी strcpy(3) से

:

strcpy() फ़ंक्शन प्रतियां स्ट्रिंग src द्वारा इंगित किए समाप्त अशक्त बाइट ('\ 0'), करने के लिए बफर गंतव्य से की ओर इशारा सहित ।

तो तुम,

strcpy(s, "hello"); 

क्योंकि आकार 5 है द्वारा NULL बाइट

char *s = new char [6]; 
strcpy(s, "hello"); 
0

आप s2 सूचक भ्रष्ट कर दिया है के लिए 6 बाइट्स स्ट्रिंग के लिए 5 और 1 आरक्षित करने की जरूरत है जबकि आप चूक गए हैं कि strcpy स्ट्रिंग टर्मिनेटर शामिल है।

3

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

char *s1 = new char [strlen(s) + 1]; 
... 
char *s = new char [5 + 1]; 

दोनों ही मामलों में, आप स्ट्रिंग प्लस समाप्त '\ 0' के लिए एक बाइट के लिए पर्याप्त जगह आवंटित करना चाहिए।

जैसा कि अन्य ने पहले से ही बताया है, सी ++ के साथ std::string का उपयोग करना आसान और सुरक्षित है।

std::string ff (const std::string &s){ 
    std::string s1(s); 
    // do something else with s1 
    return s1; 
} 

int main(int argc, char* argv[]) 
{ 
    std::string s("hello"); 
    std::string s2 = ff(s); 
    return 0; 
} 

और अगर यह सिर्फ स्ट्रिंग को कॉपी है: आवंटन और स्मृति की रिहाई या '\ 0' बाइट्स पर ध्यान देने के साथ कोई उपद्रव

std::string s("hello"); 
std::string s2(s);