2015-02-17 8 views
8

उदाहरण के लिए:स्थानीय चर पर फ़ंक्शन को फ़ंक्शन करने के लिए पास करना: क्या यह सुरक्षित है?

void func1(){ 
    int i = 123; 
    func2(&i); 
} 
void func2(int *a){ 
    *a = 456; 
} 

जब func1func2 बुला, स्थानीय चर के लिए सूचक func2 में भेजा जाता है - सूचक ढेर की ओर इशारा कर रहा है। क्या यह सी के नियमों के लिए सुरक्षित है?

धन्यवाद।

+2

वैरिएबल नष्ट होने के बाद एक चर के लिए पॉइंटर का उपयोग करना असुरक्षित है। तुम यहाँ ऐसा नहीं कर रहे हो। – immibis

+2

ओटी: यदि कार्य के लिए कोई तर्क परिभाषित नहीं किया गया है तो यह 'void func1 (शून्य) होना चाहिए। – alk

+0

[संभावित रूप से कार्य करने के लिए ऑटो चर से पॉइंटर को सुरक्षित करने के लिए सुरक्षित?] (Http://stackoverflow.com/questions/17798785/safe-to-pass-pointer-to-auto-variable-to- कार्यक्षमता) – ravron

उत्तर

14

i का दायरा func1 है और यह func2 पर कॉल से बाहर निकलता है। तो यह पूरी तरह से सुरक्षित है।

+0

क्या आप यह प्रश्न देख सकते हैं: "http: // stackoverflow। कॉम/प्रश्न/34774322/एएम-आई-कर-सही-बाय-पासिंग-पॉइंटर-टू-ऑटो-वेरिएबल " –

2

हां स्थानीय परिवर्तक को पॉइंटर पास करना सुरक्षित है लेकिन आप किसी फ़ंक्शन से स्वचालित स्थानीय चर में पॉइंटर वापस नहीं कर सकते हैं।

+0

क्या आप कृपया इस प्रश्न का उत्तर दें: http://stackoverflow.com/questions/34774322/am-i-doing-correct-by-passing-pointer-to-auto-variable –

1

हां, आपका कोड सुरक्षित है।

जब तक ऑब्जेक्ट का जीवनकाल खत्म नहीं हो जाता है, तब तक आपके जैसे स्थानीय चर पारित करना सुरक्षित है।

1

क्या यह सी के नियमों के लिए सुरक्षित है?

आप जो कर रहे हैं वह सुरक्षित है क्योंकि स्थानीय चर अभी भी वैध है और दायरे में है। स्थानीय दायरे को अपने दायरे से बाहर करना अपरिभाषित व्यवहार है लेकिन यह पूरी तरह से ठीक है

1

अपने मामले में, आप i सुरक्षित रूप से &i का सुरक्षित रूप से उपयोग कर सकते हैं।

अब, जैसा कि हम i देख सकते हैं func1() के अंत तक जीवन भर है। जैसा कि func2() को func1() से बुलाया जा रहा है और func1() अभी तक निष्पादन समाप्त नहीं हुआ है, इसलिए i अभी भी मान्य है। (तुरंत return, की स्थानीय चर के बाद

है यही कारण है कि, आम तौर पर एक और कार्य करने के लिए एक स्थानीय चर का पता गुजर आमतौर पर अनुमति है (चर के जीवनकाल खत्म नहीं हुआ है), लेकिन, return एक स्थानीय चर का पता ing कार्य मौजूद है) की अनुमति नहीं है।

टी एल; डॉ: आप सुरक्षित रूप से जैसा कि यहाँ दिखाया func2() के तर्क के रूप में उपयोग कर सकते हैं &i

+0

* स्कोप * पहचानकर्ताओं (चर नहीं) पर लागू होता है और इसका मतलब है कि वह पहचानकर्ता कहां दिखाई दे रहा है, इसलिए' i' 'func2' में दायरे में नहीं है। शायद आप * जीवनकाल * की तलाश में हैं। –

+0

@MattMcNabb सर, अब मैं अद्यतन, कृपया समीक्षा करें। –

+0

@ सौरवशोश सर क्या आप यह प्रश्न देख सकते हैं। "http://stackoverflow.com/questions/34774322/am-i-doing-correct-by-passing-pointer-to-auto-variable" –

3

जैसा कि पहले के अधिकांश उत्तरों में बताया गया है, यह आपके विशेष मामले में सूचक को func2() पर पास करने के लिए पूरी तरह से सुरक्षित है।

सॉफ़्टवेयर के असली दुनिया के टुकड़े में हालांकि, मैं इस हानिकारक पर विचार करता हूं क्योंकि आपके पास func2() पर आपके नियंत्रण के साथ नियंत्रण नहीं है। func2() बाद में बिंदु पर अतुल्यकालिक रूप से इसका उपयोग करने के लिए इसके पैरामीटर में उपनाम बना सकता है। और उस समय, स्थानीय उपरोक्त int i चलाया जा सकता है जब यह उपनाम बाद में उपयोग किया जाता है।

तो स्थानीय बिंदु (स्वचालित) चर के लिए एक पॉइंटर पास करने के मेरे दृष्टिकोण से अत्यंत खतरनाक है और इसे टालना चाहिए।

आप ऐसा कर सकते हैं, तो आप के रूप में static int i;

उस मामले में func1() में चर घोषित, यह सुनिश्चित किया जाता है, कि i के लिए स्मृति पुनर्नवीनीकरण नहीं हो जाएगी और ओवरराइट। हालांकि आपको एक समवर्ती वातावरण में इस स्मृति में अभिगम नियंत्रण के लिए कुछ म्यूटेक्स लॉकिंग सेट अप करने की आवश्यकता होगी।

इस समस्या को स्पष्ट करने के लिए यहां कुछ कोड है जो मैंने कल अपने ग्राहक पर सॉफ़्टवेयर परीक्षण करते समय ठोकर खाई थी। और हाँ, यह दुर्घटनाओं ...

void func1() 
{ 
    // Data structure for NVMemory calls 
    valueObj_t NVMemObj; 

    // a data buffer for eeprom write 
    UINT8 DataBuff[25]; 
    // [..] 
    /* Assign the data pointer to NV Memory object */ 
    NVMemObj.record = &DataBuff[0]; 
    // [..] 
    // Write parameter to EEPROM. 
    (void)SetObject_ASync(para1, para2, para3, &NVMemObj); 
    return; 
} 

void SetObject_ASync(para1, para2, para3, valueObj_t *MemoryRef) 
{ 
    //[..] 
    ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr = MemoryRef->record; 
    //[..] 
    return; 
} 

इस मामले में, DataBuff में डेटा लंबे जब ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr में सूचक EEPROM करने के लिए डाटा स्टोर करने के लिए इस्तेमाल किया जाता है चला गया है।

इस कोड को ठीक करने के लिए, यह कम से कम static UINT8 DataBuff[25]; इसके अतिरिक्त, यह भी static valueObj_t NVMemObj घोषित करने के लिए हम नहीं जानते कि के रूप में क्या कहा जाता है कि समारोह सूचक के साथ कर रही है विचार किया जाएगा की घोषणा करने के लिए आवश्यक है।

यह संक्षिप्त में कहें: टी एल; डॉ

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

बस मेरे 2 सेंट।

+3

"func2() इसके पैरामीटर में उपनाम का उपयोग करने के लिए उपनाम बना सकता है समय में बाद में बिंदु "। फिर भी यह एक समारोह में गुजरने वाली मॉलोस्ड मेमोरी के बारे में भी कहा जा सकता है ... यह उस पर एक उपनाम बना सकता है जिसे कॉलर के बाद एक्सेस करने की कोशिश करता है बाद में स्मृति को मुक्त करता है। यहां बिंदु यह है कि कॉलर कुछ भी गलत नहीं कर रहा है, लेकिन * फ़ंक्शन कहा जाता है * संदर्भ संदर्भ (जहां? वैश्विक में?) अपने स्वयं के तर्कों के लिए कि यह * बाद में कॉल * में पुन: उपयोग करता है। यह भी मान लें कि यह एक सुरक्षित प्रारंभिक बिंदु है क्योंकि उन्हें मुक्त होने की आवश्यकता नहीं है। TLDR; स्वचालित चर = अच्छा। फंक्शंस पॉइंटर्स को उनके तर्क = खराब में रखते हैं। – aaa90210

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