2010-02-02 8 views
7

मेरे पास एक संरचना malloc() 'd है, और उनका उपयोग करने के बाद, मैं इसे मुक्त करना चाहता हूं, लेकिन मेरा प्रोग्राम यहां जमा हो जाता है। कोई मुझे बता सकता हैं मुझसे क्या गलती हो रही है?कैसे मुक्त() एक malloc() 'डी संरचित सही ढंग से?

struct data 
{ 
char *filename; 
char *size; 
}; 
//primarypcs is a long type variable 
struct data *primary = (struct data *)malloc(primarypcs * sizeof(struct data)); 
memset(primary, 0, sizeof(struct data *) * primarypcs); 
... 
... 
... 
for (i = 0; i < primarypcs; i++) 
{ 
    free(primary[i].filename); //<----my program freezes here 
    free(primary[i].size);  //<----or here 
} 
free(primary); 

अग्रिम धन्यवाद:

यहाँ मेरी कोड है!

kampi

संपादित करें:

कैसे कर सकते हैं मैं फ़ाइल नाम और आकार के लिए सही ढंग से malloc स्मृति?

EDIT2:

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

+2

मुझे आपको 'फ़ाइल नाम' और 'आकार' के लिए स्मृति आवंटित नहीं दिख रहा है। –

+2

हाँ, आपके कोड में एक बग है: मॉलोक में आप आकार (संरचना डेटा) का उपयोग करते हैं जो सही लगता है, फिर भी याद में आप आकार (संरचना डेटा *) का उपयोग करते हैं जो आकार का आधा है। इसका मतलब है कि आपके पास केवल शून्य-आधा स्मृति है और जब आप इसे मुक्त करने का प्रयास करते हैं तो स्मृति का अंतिम 1/2 बारफ होगा। उत्तर मुफ्त (प्राथमिक) होना चाहिए; और कुछ और नहीं – cmroanirgo

+0

यदि यह सी ++ है, तो आपको नए का उपयोग करना चाहिए और हटा देना चाहिए। – Xorlev

उत्तर

7

आप पूरे कोड को प्रस्तुत नहीं कर रहे हैं, जहां कई चीजें गलत हो सकती हैं, लेकिन एक त्रुटि पहले से ही स्पष्ट है। लाइन

memset(primary, 0, sizeof(struct data *) * primarypcs); 

ऐसा नहीं कर रहा है जो आपको लगता है कि यह कर रहा है। यह sizeof में गलती टाइप करने के कारण संपूर्ण सरणी को शून्य नहीं कर रहा है। यह सबसे अधिक संभावना होने के लिए

memset(primary, 0, sizeof(struct data) * primarypcs); 

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

सामान्य रूप से, ऐसी त्रुटियों के अवसर को कम करने के लिए घोषणाओं को छोड़कर, अपने कार्यक्रम में प्रकार के नामों का उल्लेख करना सबसे अच्छा है। अपने प्रश्न सी ++ (हालांकि यह निश्चित रूप से सी की तरह दिखता है) टैग है के बाद से, यह प्रकार से छुटकारा पाने के लिए संभव नहीं है malloc पर डाले, लेकिन अन्यथा मैं कहता था कि निम्नलिखित बेहतर

struct data *primary = (struct data *) malloc(primarypcs * sizeof *primary); 
memset(primary, 0, primarypcs * sizeof *primary); 

लग रहा है और, जैसा कि एक तरफ ध्यान दें, यदि आपका कोड सी ++ बनना था, तो आप एक ही परिणाम एक और अधिक सुंदर, कॉम्पैक्ट और पोर्टेबल रास्ते में मिल सकता है

data *primary = new data[primarypcs](); 

इस मामले में बेशक आप उपयोग कर स्मृति पुनःआवंटन करना होगा free के बजाय उपयुक्त सी ++ कार्यक्षमता।

+0

हाय! आपकी मदद के लिए धन्यवाद। यह मेरी गलतियों में से एक था, मेरे जवाब से मेरे कोड को सही करने के बाद, मेरा प्रोग्राम अभी भी ठंडा हो गया। बाद में मुझे एहसास हुआ कि मैंने अपने चर में से एक को गलत टाइप किया है, और मैंने केवल 5 वस्तुओं के लिए स्मृति आवंटित की है, हालांकि मैंने संरचना में 5 से अधिक आइटम डाले हैं। धन्यवाद फिर से! – kampi

3

संरचना में स्ट्रिंग आवंटित कैसे हैं? यदि उन्हें स्थैतिक रूप से स्थिरांक के लिए आवंटित किया गया है, तो उन्हें इस तरह से मुक्त न करें, और इसकी आवश्यकता सभी free (primary); मॉलोकैड नहीं होने वाली चीज़ को मुक्त करने से हीप मैनेजर को दिल की जब्त होगी।

यदि स्ट्रिंग पॉइंटर्स malloc() या calloc() द्वारा सेट किए गए हैं, तो यह उचित तरीका है।

0

free (primary); के साथ अपने कोड के निचले हिस्से में लूप को प्रतिस्थापित करना चाहिए।

0

ऐसा इसलिए है क्योंकि आपने स्पष्ट रूप से filename और size के लिए स्मृति आवंटित नहीं किया है। तो free(primary[i].filename); या free(primary[i].size); करने की कोशिश कर रहे अपरिभाषित व्यवहार का आह्वान करेगा।

बस free(primary) पर्याप्त है।

संपादित:

यह सवाल टैग किया गया है सी ++। तो C++ तरीका उपयोगकर्ता परिभाषित प्रकारों के लिए malloc के बजाय new का उपयोग करना है।

new और malloc के बीच मतभेद के लिए, this.

सी ++ में पर एक नजर है तुम सिर्फ

data *primary = new data[primarypcs](); //() for value initialization 
+0

नमूना कोड को ठीक के रूप में माना जा सकता है, मान लीजिए कि वे व्यक्तिगत रूप से फ़ाइल नाम को मॉलोक करते हैं। एक malloc'ed 'आकार' होने के कारण संदिग्ध रूप से छोटी गाड़ी लगती है, एक आकार_टी शायद बेहतर हो जाएगा (जब तक कि यह वास्तव में एक char स्ट्रिंग न हो) – cmroanirgo

0

लिखने के लिए इस memset में अपनी समस्या है, जिसके लिए मुद्दों के सभी प्रकार की वजह से ठीक करता है की जरूरत है आप।

memset(primary, 0, sizeof(struct data) * primarypcs); 

संक्षेप में, आपने अपनी 'प्राथमिक' संरचना के अंत में अनियमित स्मृति छोड़ी।

2

आप सी ++ में यह कर रहे हैं, तो आप (लगभग निश्चित रूप से) की तरह कुछ का उपयोग नहीं करना चाहिए:

data *primary = new data[primarypcs](); 

इसके बजाय, आप की तरह कुछ का उपयोग करना चाहिए:

struct data { 
    std::string filename; 
    std::string size; 
}; 

std::vector<data> primary(primarypcs); 

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

सी ++ में सरणी नया (जैसे new x[y]) का उपयोग कुछ ऐसा है जो आप बिना बेहतर हैं। एक बार एक समय (15 साल पहले या तो) यह लगभग एकमात्र उपकरण उपलब्ध था, इसलिए इसका (क्रोध) उपयोग लगभग अपरिहार्य था - लेकिन वह दिन बहुत पुराना है, और पिछले 10 वर्षों में यह वास्तव में अच्छा था इसका उपयोग करने का कारण।

चूंकि अनिवार्य रूप से "वेक्टर की तरह कुछ लागू करने के अलावा" के बारे में एक टिप्पणी है, इसलिए मैं यह इंगित करूंगा कि, नहीं, जब भी आप वेक्टर लागू कर रहे हों, तब भी आप सरणी का उपयोग नहीं करते - आप (अप्रत्यक्ष रूप से, एक के माध्यम से आवंटक) कच्चे मेमोरी आवंटित करने के लिए ::operator new का उपयोग करें, उस स्मृति में ऑब्जेक्ट्स बनाने के लिए नया प्लेसमेंट, और वस्तुओं को नष्ट करने के लिए स्पष्ट dtor कॉल।

+0

+1 'std :: vector' –

1

के रूप में अन्य लोगों ने कहा, वहाँ स्निपेट में दो स्पष्ट रूप से गलत बातें आप दिखाया है कर रहे हैं:

  1. आप structs सिर्फ आवंटित की filename और size सदस्यों के लिए स्मृति को आबंटित नहीं है,
  2. आपका memset() कॉल गलत आकार का उपयोग करता है।

आपका memset() कॉल सरलीकृत और सुधारा जा सकता है द्वारा:

memset(primary, 0, primarypcs * sizeof *primary); 

अपने कोड के साथ एक और सूक्ष्म समस्या है: सी मानक गारंटी नहीं है कि सब-बिट शून्य नल पॉइंटर स्थिर है (यानी, न्यूल), इसलिए मेमसेट() NULL पर पॉइंटर सेट करने का सही तरीका नहीं है। क्या आप क्या करना चाहते करने का एक पोर्टेबल तरीका है:

size_t i; 
for (i=0; i < primarypcs; ++i) { 
    primary[i].filename = NULL; 
    primary[i].size = NULL; 
} 

filename और size के लिए स्मृति को आबंटित करने के लिए, यह आप क्या चाहते हैं पर निर्भर करता है। मान लें कि आप निर्धारित करते हैं कि filename को n बाइट्स की आवश्यकता है, और size को m की आवश्यकता है। फिर, कुछ इस तरह करने के लिए अपने पाश परिवर्तन:

size_t i; 
for (i=0; i < primarypcs; ++i) { 
    size_t n, m; 
    /* get the values of n and m */ 
    primary[i].filename = malloc(n * sizeof *primary[i].filename); 
    primary[i].size = malloc(m * sizeof *primary[i].size); 
} 

आप sizeof *primary[i].filename और sizeof *primary[i].size ऊपर से साथ गुणा छोड़ सकते हैं अगर आप चाहते हैं: सी गारंटी देता है कि sizeof(char) 1. है मैं पूर्णता के लिए और मामले के लिए ऊपर लिखा था जब filename और size परिवर्तन प्रकार।

इसके अलावा, यह है कि अगर filename लंबाई k की एक श्रृंखला है, तो आप इसके लिए (k+1) बाइट्स समाप्त 0 (ताकि ऊपर n == k+1) की वजह से की जरूरत है, ध्यान दें।

यदि मुझे अनुमान लगाना था, तो आप संबंधित filename की लंबाई को संग्रहीत करने के लिए size चाहते हैं? यदि ऐसा है, sizechar * नहीं होना चाहिए लेकिन size_t होना चाहिए। लेकिन चूंकि मुझे नहीं पता कि आप filename और size का उपयोग करने की योजना कैसे बनाते हैं, मुझे यकीन नहीं है।

malloc() के वापसी मूल्य की जांच करना सुनिश्चित करें। यह विफलता के लिए NULL देता है। मैंने सादगी के लिए उपरोक्त कोड से चेक छोड़ा।

आपकी पोस्ट को सी ++ भी टैग किया गया है, इसलिए यदि आप सी ++ का उपयोग करने के इच्छुक हैं, तो एक सी ++ समाधान भी उपलब्ध है।

+0

की सिफारिश करने के लिए +1! फ़ाइल नाम और आकार के लिए मुझे सही ढंग से स्मृति आवंटित कैसे करना चाहिए? – kampi

+0

हाय! एक उद्देश्य के लिए आकार char * है। मुझे फ़ाइल का आकार बहुत लंबा लगता है, लेकिन बाद में मुझे इसे चार के रूप में उपयोग करना होगा, इसलिए मैं इसे int से char में परिवर्तित करता हूं, और फिर इसे संरचना में संग्रहीत करता हूं। – kampi

0

आप पूरे सरणी को याद करने में विफल रहे हैं जिसके परिणामस्वरूप एक कचरा स्मृति सूचक को मुक्त किया जा रहा है। इस गलती से बचने के लिए malloc/memset के बजाय calloc का उपयोग करें:

struct data *primary = calloc(primarypcs, sizeof(struct data)); 

यह दोनों आवंटित और स्मृति साफ करता है। आप भी सभी struct data प्रविष्टियों को प्रारंभ करना चाहते हैं:

for (i = 0; i < primarypcs; ++i) { 
    primary[i].filename = malloc(...); 
    primary[i].size = malloc(...); 
} 

(आप का वर्णन नहीं करते क्या फ़ाइल नाम आकार के होते हैं कर रहे हैं, तो मैं छोड़ ... में आप को भरने के लिए के लिए)।

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