2008-09-19 7 views
17

मुझे लगता है कि मैं सबसे बुनियादी मामले के लिए नीचे मिल गया है:फ़ंक्शन कॉल के अंदर मॉलोक रिटर्न पर मुक्त हो रहा है?

int main(int argc, char ** argv) { 
    int * arr; 

    foo(arr); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

void foo(int * arr) { 
    arr = (int*) malloc(sizeof(int)*25); 
    arr[3] = 69; 
} 

उत्पादन यह है:

> ./a.out 
car[3]=-1869558540 
a.out(4100) malloc: *** error for object 0x8fe01037: Non-aligned pointer 
         being freed 
*** set a breakpoint in malloc_error_break to debug 
> 

किसी को भी, जहां मेरी समझ विफल हो रहा है पर प्रकाश डाल सकती है, यह था बहुत सराहना कीजिए।

उत्तर

47

पारित आप सूचक मूल्य से, द्वारा नहीं पारित संदर्भ, तो जो भी आप foo के अंदर arr के साथ करते हैं वह foo-function के बाहर कोई फर्क नहीं पड़ता है। m_pGladiator के रूप में लिखा है एक तरह से एक संदर्भ इस तरह सूचक को घोषित करने के लिए है (सी ++ btw में ही संभव सी संदर्भों के बारे में पता नहीं है।):

int main(int argc, char ** argv) { 
    int * arr; 

    foo(arr); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

void foo(int * &arr) { 
    arr = (int*) malloc(sizeof(int)*25); 
    arr[3] = 69; 
} 

एक और (बेहतर imho) रास्ता सूचक के रूप में पारित नहीं करने के लिए है एक तर्क लेकिन एक सूचक वापस करने के लिए:

int main(int argc, char ** argv) { 
    int * arr; 

    arr = foo(); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

int * foo(void) { 
    int * arr; 
    arr = (int*) malloc(sizeof(int)*25); 
    arr[3] = 69; 
    return arr; 
} 

और आप एक पॉइंटर को पॉइंटर पास कर सकते हैं। संदर्भ द्वारा पारित करने के लिए यह सी तरीका है। वाक्य रचना पेचीदा एक सा है, लेकिन अच्छी तरह से - कि कैसे सी है ...

int main(int argc, char ** argv) { 
    int * arr; 

    foo(&arr); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

void foo(int ** arr) { 
    (*arr) = (int*) malloc(sizeof(int)*25); 
    (*arr)[3] = 69; 
} 
+0

क्या मैं बस कह सकता हूं, कृपया मॉलोक के वापसी मूल्य को न डालें? यह आवश्यक नहीं है और त्रुटियों को छुपा सकता है। – freespace

+0

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

+0

उत्तर के बिना आपको फांसी छोड़ने के बारे में खेद है: टिप्पणियों में जवाब खोजने का कोई अच्छा तरीका नहीं है जब तक कि मैं अपनी सभी टिप्पणियों का चुनाव नहीं करता :) :) मैंने http://stackoverflow.com/questions/108768/needless- पॉइंटर-कास्ट-इन-सी # 108781 – freespace

6

आपने foo में arr आवंटित किया है, लेकिन कॉल पॉइंट मान कॉल स्टैक में संग्रहीत है। यदि आप ऐसा करना चाहते हैं, इसे इस तरह कार्य करें:

void foo(int ** arr) { 
    *arr = (int *)malloc(sizeof(int) * 25); 
    (*arr)[3] = 69; 
} 

और मुख्य में, बस foo के लिए सूचक (foo की तरह (& आगमन))

0

आप अपने तर्क (आगमन) अगर यह संदर्भ (&) द्वारा में पारित नहीं कर रहा है के मूल्य को नहीं बदल सकते। आम तौर पर, आप सूचक को वापस करना चाहते हैं, इसलिए आपकी विधि होनी चाहिए:

arr = foo();

तर्कों को फिर से सौंपने का प्रयास करने के लिए यह बुरा जुजू है; मैं (&) समाधान की सिफारिश नहीं करता हूं।

3

foo int सूचक की एक स्थानीय प्रति प्राप्त करता है, इसके लिए स्मृति को आवंटित करता है और जब यह गुंजाइश से बाहर हो जाता है तो उस स्मृति को रिसाव करता है।

एक तरीका यह तय करने के लिए सूचक वापस जाने के लिए foo पाने के लिए:

int * foo() { 
    return (int*) malloc(sizeof(int)*25); 
} 

int main() { 
    int* arr = foo(); 
} 

एक और foo एक सूचक

void foo(int ** arr) { 
    *arr = malloc(...); 
} 

int main() { 
    foo(&arr); 
} 

C++ में इसे करने के लिए foo संशोधित करने के लिए आसान है करने के लिए एक सूचक पारित करने के लिए है एक सूचक के संदर्भ को स्वीकार करें। केवल परिवर्तन आप सी में जरूरत ++

void foo(int * & arr) 
1

को foo बदलने के लिए अपने मूल्य द्वारा सूचक गुजर रहे हैं के बाद से, मुख्य अंदर आगमन सूचक आबंटित स्मृति की ओर इशारा करते नहीं है। इसका मतलब है कि दो चीजें: आपको अपने आप को एक स्मृति रिसाव मिल गया है (नहीं, फ़ंक्शन फ़ू पूर्ण होने के बाद स्मृति मुक्त नहीं होती है), और जब आप मुख्य रूप से एआर पॉइंटर तक पहुंचते हैं तो आप स्मृति की कुछ मनमानी रेंज तक पहुंच रहे हैं, इसलिए आप डॉन नहीं करते हैं 3 मुद्रित नहीं होगा और इसलिए मुफ्त() काम करने से इंकार कर देता है। आप भाग्यशाली हैं कि मुख्य रूप से arr [3] तक पहुंचने पर आपको सेगमेंटेशन गलती नहीं मिली।

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