2010-06-05 22 views
8

मैंने सी/सी ++ में प्रोग्रामिंग करते समय बहुत सारे प्रोग्रामर कह रहे हैं और लिखते हैं, स्मृति से संबंधित बहुत सारे मुद्दे हैं। मैं सी/सी ++ में प्रोग्राम सीखने की योजना बना रहा हूं। मेरे पास सी/सी ++ का शुरुआती ज्ञान है और मैं कुछ संक्षिप्त नमूना देखना चाहता हूं क्यों सी/सी ++ में मेमोरी प्रबंधन के साथ समस्या हो सकती है। कृपया कुछ नमूने प्रदान करें।सी/सी ++ में स्मृति समस्या क्यों है?

+10

बस इसलिए कि आपको स्मृति को आवंटित और डिलीकेट करने की आवश्यकता है। –

+0

जब आप स्मृति आवंटित करते हैं और को हटाते हैं तो यह कैसे समस्या बनता है? – LinuxNewbie

+2

आप गलतियां करते हैं :) –

उत्तर

16

सी या सी ++ में स्मृति को दूषित या रिसाव करने के कई तरीके हैं। इन त्रुटियों का निदान करने में सबसे कठिन कुछ है, क्योंकि वे अक्सर आसानी से पुन: उत्पन्न नहीं होते हैं।

उदाहरण के लिए, आपके द्वारा आवंटित मुक्त स्मृति में विफल होना आसान है। उदाहरण के लिए, यह एक "डबल मुक्त" क्या करेंगे दो बार a मुक्त करने की कोशिश कर और b मुक्त करने में नाकाम रहने:

char *a = malloc(128*sizeof(char)); 
char *b = malloc(128*sizeof(char)); 
b = a; 
free(a); 
free(b); // will not free the pointer to the original allocated memory. 

एक उदाहरण बफर लंघन, जो मनमाने ढंग से स्मृति भ्रष्ट इस प्रकार है। यह एक बफर ओवररन है क्योंकि आप नहीं जानते कि str कितना समय है। यदि यह 256 बाइट से अधिक लंबा है, तो यह उन बाइट्स मेमोरी में मेमोरी में लिख देगा, संभवतः आपके कोड को ओवरराइट करना संभवतः नहीं।

void somefunc(char *str) { 
    char buff[256]; 
    strcpy(buff, str); 
} 
+0

धन्यवाद, यह एक अच्छा नमूना है। मैं इसे ध्यान में रखूंगा। सी या सी ++ के लिए – LinuxNewbie

+2

+1! – AndrejaKo

+0

मुझे इस जवाब के सी ++ को संपादित करने के लिए खुद को रोकना होगा, इसके अंदर यह शुद्ध सी कोड दिया गया है ... –

3

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

+0

जब प्रोग्रामर मेमोरी आवंटित और डिलीकेट कर रहा है तो उसे कचरा संग्रहण क्यों चाहिए? – LinuxNewbie

+1

@LinuxNewbie: वह नहीं करता! सी ++ स्वचालित कचरा संग्रह नहीं करता है। यहां एक नज़र डालें: http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29 – nico

+2

"आपको मैन्युअल रूप से आवंटित करने और स्मृति को हटाने की आवश्यकता है" -> जरूरी नहीं।ऐसे उपकरण हैं जो मैन्युअल रूप से स्मृति को हटाने की आवश्यकता को कम करते हैं, उदाहरण के लिए 'boost :: shared_ptr '। – fredoverflow

3

सी और सी ++ में सामान्य स्मृति प्रबंधन समस्याओं में से एक सरणी पर जांच की सीमाओं की कमी से संबंधित है। जावा के विपरीत (उदाहरण के लिए), सी और सी ++ यह सुनिश्चित करने के लिए जांच नहीं करते हैं कि सरणी अनुक्रमणिका वास्तविक सरणी सीमाओं के भीतर आती है। इस वजह से, गलती से स्मृति को ओवरराइट करना आसान है। उदाहरण (C++) के लिए:

char *a = new char[10]; 
a[12] = 'x'; 

ऊपर कोड के साथ जुड़े नहीं संकलन या रनटाइम त्रुटि, सिवाय इसके कि अपने कोड याद है कि नहीं होना चाहिए ऊपर लिख देगा होगा।

+0

इस नमूने के लिए धन्यवाद। – LinuxNewbie

+0

"उपरोक्त कोड से जुड़े कोई संकलन या रनटाइम त्रुटि नहीं होगी" -> आप [स्मार्ट मेमोरी रूटीन] का उपयोग कर सकते हैं (http://stackoverflow.com/questions/2835416/critique-my-non-intrusive-heap-debugger) रनटाइम पर बफर ओवरफ्लो का पता लगाने के लिए;) – fredoverflow

+0

कई कंपाइलर और ऑपरेटिंग सिस्टम रनटाइम पर इसके लिए त्रुटियां जारी करेंगे, जैसे विंडोज़ पर एवी और विजुअल स्टूडियो के लिए सीआरटी में डीबग दावे। – Puppy

7

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

स्मृति प्रबंधन को कीड़े की एक संख्या के लिए नेतृत्व कर सकते हैं:

  • आप कुछ स्मृति जारी करने के लिए भूल जाते हैं, तो आप एक स्मृति रिसाव
  • आप और अधिक स्मृति से आप किसी दिए गए के लिए अनुरोध किया है का उपयोग करते हैं है सूचक, आपके पास एक बफर ओवररन है।
  • आप स्मृति जारी करने और इसे करने के लिए एक "झूलते सूचक" का उपयोग करते रहें हैं, तो आप अपरिभाषित व्यवहार (आमतौर पर कार्यक्रम दुर्घटनाओं)
  • है आप अपने सूचक arithmetics अशुद्ध गणना हैं, तो आप एक दुर्घटना, या भ्रष्ट डेटा
है

और इनमें से कई समस्याएं निदान और डीबग करने के लिए बहुत कठिन हैं।

+0

क्या आप मुझे दिखा सकते हैं कि थोड़ी मेमोरी का अनुरोध कैसे करें? मॉलोक बाइट्स की एक पूरी संख्या लेता है! –

+0

@Pete: ठीक है, तथ्य यह है कि आप उन्हें 8 के बंच में प्राप्त करते हैं, यह मेरे बयान के विपरीत नहीं है कि आपको उन्हें मैन्युअल रूप से अनुरोध करना है, है ना? –

+0

तो मैंने * हर * महाद्वीप का दौरा किया है क्योंकि मैंने उनमें से 1/8 का दौरा किया है? –

5

मैं सी में कार्यक्रम जानने के लिए योजना बना रहा हूँ/C++

वास्तव में क्या आपको लगता है कि द्वारा मतलब है? क्या आप सी में प्रोग्राम करना सीखना चाहते हैं, या आप सी ++ में प्रोग्राम करना सीखना चाहते हैं? मैं एक ही समय में दोनों भाषाओं को सीखने की सिफारिश नहीं करता।

किसी उपयोगकर्ता के परिप्रेक्ष्य से, सी ++ में मेमोरी प्रबंधन सी से बहुत आसान है, क्योंकि इसमें से अधिकांश वर्गों द्वारा encapsulated है, उदाहरण के लिए std::vector<T>। एक वैचारिक परिप्रेक्ष्य से, सी की स्मृति प्रबंधन बहस बहुत आसान है। असल में, केवल malloc और free :)

+0

असल में मुझे एक छोटी उपयोगिता का विचार है, इसलिए मैं ऐसा करने के बारे में सोच रहा था कि सी (+ सी ++ मुझे लगता है कि सी ++ अब ओओपी अवधारणाओं और डिजाइन पर विचार करने से थोड़ा दूर है)। तो मैं उस उपयोगिता को सी ++ में बदलने की योजना बना रहा हूं जो मुझे सी ++ सीखने का मौका देगा। मैं 9 ~ 11 महीनों में अपनी उपयोगिता को खत्म करने की उम्मीद कर रहा हूं (उम्मीद कर रहा हूं)। – LinuxNewbie

+0

@ लिनक्स: सी ++ के लिए एक स्टेपिंग पत्थर के रूप में सीखना सी * स्ट्रॉस्ट्रप द्वारा अनुशंसित नहीं है * (http://www.research.att.com/~bs/bs_faq.html#prerequisite)। – fredoverflow

+1

@LinuxNewbie: सी ++ सी से काफी आसान है, क्योंकि उन ओओपी अवधारणाओं से आपको काम का पूर्ण शिटलोड करने से बचाया जाएगा। – Puppy

2

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

5

मैं ईमानदारी से कह सकता हूं कि सी ++ में प्रोग्रामिंग करते समय मुझे स्मृति आवंटन के साथ कोई "समस्या" नहीं है। आखिरी बार जब मेरे पास मेमोरी रिसाव था 10 साल पहले, और मेरे हिस्से पर अंधेरा मूर्खता के कारण था। यदि आप आरएआईआई, मानक लाइब्रेरी कंटेनर और सामान्य ज्ञान के एक छोटे से मोडिकम का उपयोग करके कोड लिखते हैं, तो समस्या वास्तव में मौजूद नहीं है।

1

अब तक एक बात का उल्लेख नहीं किया गया है और आप मैन्युअल रूप से स्मृति का प्रबंधन क्यों करना चाहते हैं। मेमोरी मैनेजिंग सही करना मुश्किल है, खासकर जब एक प्रोग्राम अधिक जटिल हो जाता है (विशेष रूप से जब आप थ्रेड का उपयोग करते हैं और जब स्मृति के टुकड़े का जीवनकाल जटिल हो जाता है (यानी जब यह मुश्किल हो जाता है जब आपको यह कहने में कठिनाई होती है कि आपको इसकी आवश्यकता नहीं है जानकारी का टुकड़ा)) यहां तक ​​कि शक्तिशाली आधुनिक प्रोग्रामिंग टूल जैसे वाल्ग्रिंड के साथ भी।

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

बहुत सारे "आधुनिक सी ++" (यह कहा गया है कि सी ++ को इसका उपयोग करने के तरीके के आधार पर कई भाषाओं के रूप में सोचा जा सकता है) कक्षाओं (या एक्स और वाई सी ++ फीचर) के साथ सी के विपरीत, एक समझौता का उपयोग करते हैं अक्सर वैकल्पिक वैकल्पिक जीसी/स्वचालित मेमोरी प्रबंधन का उपयोग करते हुए (ध्यान दें कि वैकल्पिक जीसी स्मृति प्रबंधन में और भी खराब हो सकता है, क्योंकि अनिवार्य है क्योंकि जब यह अनिवार्य है तो यह एक सरल प्रणाली है) और कुछ मैन्युअल मेमोरी प्रबंधन। इस पर निर्भर करते हुए कि आप इसे कैसे करते हैं और जीसी का उपयोग करने और मैन्युअल मेमोरी प्रबंधन करने के कुछ फायदे और नुकसान हो सकते हैं। वैकल्पिक जीसी कुछ सी पुस्तकालयों के साथ भी उपलब्ध है लेकिन सी के बाद सी ++ के साथ यह कम आम है।

+0

+1 मैन्युअल मेमोरी काम में कौशल रखने से वास्तव में आपको यह समझने में मदद मिलती है कि जीसी सिस्टम कैसे काम करते हैं..और जब आप इसे बेहतर तरीके से करेंगे। – Rusty

2

यह स्पष्ट है कि आपको उस स्मृति को रिलीज़ करना है जो अब उपयोग में नहीं है या भविष्य में उपयोग नहीं करता है, लेकिन आपको प्रोग्राम की शुरुआत में निर्धारित करना होगा, स्मृति आवश्यकता आवश्यक होने पर स्थिर या विविध होती है। यदि यह गतिशील है तो आप अपने प्रोग्राम के काम के लिए पर्याप्त स्मृति लेते हैं, उस समय आपका प्रोग्राम अतिरिक्त मेमोरी का उपभोग कर सकता है।

इसलिए आपको उस स्मृति को रिलीज़ करना होगा जो उपयोग में नहीं है और उस समय जब आवश्यक हो। सिर्फ

तरह
struct student 
{ 
char name[20]; 
int roll; 
float marks; 
}s[100]; 

यहाँ मैं कक्षा में 100 छात्र लगता है। छात्र 100 से कम या 100 से अधिक हो सकता है। यदि 100 से अधिक हो तो आपका प्रोग्राम जानकारी खो देगा या कम 100 होगा तो कार्यक्रम चलाएगा लेकिन स्मृति की बर्बादी होगी, यह बड़ा हो सकता है।

इसलिए हम आमतौर पर निष्पादन के समय गतिशील रूप से रिकॉर्ड बनाते हैं। सिर्फ

तरह
struct student *s; 

s=(struct student *)malloc(sizeof(struct student)); 

scanf("%s %d %f",s->name,s->roll,s->marks); 

उपयोग में नहीं है, तो फिर यह momery अंतरिक्ष फार्म को हटा दें।

free(s); 

प्रोग्रामिंग के लिए यह अच्छा तरीका है, अगर आप स्मृति से नहीं हटाते हैं तो एक बार यह आपकी मेमोरी स्टैक को भर सकता है और इसे लटकाया जा सकता है।

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