2008-11-12 10 views
6

क्या मौजूदा फ़ंक्शन से पहले स्पष्ट रूप से सी के आवंटन() द्वारा आवंटित स्मृति को मुक्त करना संभव है? यदि हां, तो कैसे?फ्रीिंग एलोका-आवंटित मेमोरी

+0

क्या आप अपनी प्रेरणा की व्याख्या कर सकते हैं? लौटने से पहले आवंटित स्थान क्यों मुक्त करना चाहते हैं? – Motti

उत्तर

8

यह संभव है, लेकिन ऐसा करने के लिए कोई पूर्व-लिखित कार्य नहीं है। यह पता लगाने के लिए कि आप क्या कर रहे हैं, यह जानने के लिए आपको अपने कंपाइलर के एलोका() के कार्यान्वयन में जाना होगा, फिर अपना खुद का फ्री() लिखें। चूंकि प्रत्येक कंपाइलर alloca() अलग-अलग करता है, इसलिए आपको प्रत्येक कंपाइलर के लिए अपने फ्री() को फिर से लिखना होगा।

लेकिन मुझे विश्वास करना मुश्किल लगता है कि यह मुसीबत के लायक होगा। अगर आपको इसे स्पष्ट रूप से मुक्त करने की आवश्यकता है तो बस मॉलोक/फ्री का उपयोग करें - उन कार्यों को आमतौर पर अत्यधिक अनुकूलित किया जाता है। उनका लाभ उठाएं।

+3

एक पोर्टेबल कार्यान्वयन "शून्य फ्री (शून्य * पी) {} // बस नकली है"। – paxdiablo

+0

उम, नहीं। आप भ्रष्टाचार के बिना स्टैक पॉइंटर को स्थानांतरित नहीं कर सकते हैं, और आप स्टैक पर आइटम स्थानांतरित नहीं कर सकते हैं क्योंकि उनके पते कहीं और संग्रहीत किए जा सकते हैं। नि: शुल्क/मॉलोक काम का कारण यह है कि उनके पास उनके ढेर स्थान पर पूर्ण नियंत्रण है। – SquareCog

+4

मैंने alloca() लागू किया है, और हाँ आप एक फ्री() कर सकते हैं। आप ऑलोकै() से अधिक वस्तुओं को स्थानांतरित नहीं करेंगे - उनके पते के साथ स्थानीय लोग आवंटित स्थान से पहले आवश्यक हैं। आपको वांछित पॉइंटर्स को फ्रीएड स्पेस में छोड़ना नहीं चाहिए, वैसे भी, फ्री स्पेस के लिए आप जितना भी कर सकते हैं। –

1

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

कोई संकर नहीं है जो आपको और को स्पष्ट रूप से मुक्त करने की अनुमति देता है, यह कम से कम मानक में नहीं, फ़ंक्शन से बाहर निकलता है।

2

आप alloca() के साथ ढेर पर आवंटित कर रहे हैं; अगर कुछ और बाद में हुआ (और आप असेंबली में सबकुछ लिखने के बिना इसे नियंत्रित नहीं कर सकते हैं), तो आप केवल स्टैक को कम नहीं कर सकते हैं। तो जब तक आप अपने कार्य के ढेर फ्रेम को छोड़ नहीं देते, यह असंभव है।

यही कारण है कि यदि आप आवंटित बफर को ओवरफ्लो करते हैं तो आप वास्तव में गड़बड़ कर सकते हैं। आप कोड के ओवरराइटिंग पते को अपने फ़ंक्शन पर लौट सकते हैं, जिससे इसे कहीं और, सभी प्रकार की भयंकर चीजें कूदने लगती हैं। सावधान रहे!

मॉलोक ढेर पर काम करता है, इसलिए यही है कि यह क्या कर सकता है में यह अधिक लचीला है।

8

http://www.gnu.org/software/libc/manual/html_mono/libc.html#Variable-Size-Automatic से:

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

1

यह निरंतर उत्तीर्ण शैली (सीपीएस), बल्कि एक realloca के लिए उपयोगी होगा।

आप स्ट्रिंग की लंबाई तक वापस स्टैक को कम करने और अगले फ़ंक्शन को कॉल करने से पहले, एक फ़ंक्शन को कॉल कर सकते हैं जो स्टैक के शीर्ष पर एक स्ट्रिंग को आवंटित और छेड़छाड़ कर सकता है।

कोई वैचारिक कारण नहीं है कि क्यों फ्रीडा() नहीं हो सकता है, जो स्टैक पर शीर्षतम प्रविष्टि के अलावा कुछ भी नहीं होगा।

2

सी 99 का उपयोग करके आप Variable Length Array का उपयोग करके एक ही चीज़ प्राप्त कर सकते हैं। बस एक नए दायरे में वीएलए घोषित करें; जब दायरा निकलता है तो यह स्वचालित रूप से मुक्त हो जाएगा।

उदाहरण के लिए:

int some_function(int n) { 
    // n has the desired length of the array 
    ... 
    { // new scope 
     int arr[n]; // instead of int *arr = alloca(n*sizeof(int)); 
     // do stuff with array 
    } 
    // function continues with arr deallocated 
    ... 
} 
1

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

#include <stdio.h> 
#include <alloca.h> 

int main() 
{ 
    unsigned long p0, p1, p2; 
    p0=(unsigned long)alloca(0); 
    p1=(unsigned long)alloca((size_t) 0x1000); 
    p2=(unsigned long)alloca((size_t)-0x1000); 
    printf("p0=%lX, p1=%lX, p2=%lX\n", p0, p1, p2); 
    return 0; 
} 
बजना 2.9 के साथ

एक पुराने x64 मशीन पर, एक नमूना उत्पादन होता है:

p0=7FFF2C75B89F, p1=7FFF2C75A89F, p2=7FFF2C75B89F 

तो हम कार्यान्वयन पता तर्क -0x1 को मान्य नहीं है 000, अन्यथा हस्ताक्षरित मूल्य एक बहुत बड़ा पूर्णांक होगा। स्टैक पॉइंटर मूल रूप से 0x था ... B89F; चूंकि यह ढेर ऊपर की ओर एलोका (0x1000) बढ़ता है इसलिए स्टैक पॉइंटर (0x ... B89F - 0x1000) = 0x ... A89F बदलें। नकारात्मक आवंटन के बाद (0xA89F - (-0x1000)) स्टैक पॉइंटर 0x पर वापस चला गया ... B89F।

हालांकि, जीसीसी 4.8.3 के साथ, एक नमूना उत्पादन होता है:

p0=7FFFA3E27A90, p1=7FFFA3E26A80, p2=7FFFA3E27A70 

/usr/include/alloca.h हमने पाया में:

#ifdef __GNUC__ 
# define alloca(size) __builtin_alloca (size) 
#endif /* GCC. */ 

तो हम जानते हैं कि builtin alloca जीसीसी 4.8.3 द्वारा प्रदान किया गया कार्य इसी तरह की चीज करता है सिवाय इसके कि इसे अतिरिक्त मार्जिन के रूप में अतिरिक्त 0x10 बाइट आवंटित करें। नकारात्मक आवंटन करते समय भी यह मानता है कि यह ऊपर की ओर बढ़ता है और इसलिए 0x10 अतिरिक्त बाइट्स (- 0x10) को आरक्षित करने की कोशिश की गई है, इसलिए पी 2 = 0x ... 6 ए 80 - (-0x1000) - 0x10 = 0x ... 7A70। तो, अतिरिक्त सावधान रहें।

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