2009-02-25 11 views
46

va_end - arg_ptr रीसेट करने के लिए मैक्रो।क्या va_end के लिए वास्तव में है? क्या इसे हमेशा कॉल करना जरूरी है?

एक चर तर्क सूची तक पहुँचने के बाद, arg_ptr सूचक आमतौर पर va_end() साथ रीसेट है। मैं समझता हूं कि यदि आप सूची को फिर से शुरू करना चाहते हैं, तो इसकी आवश्यकता है, लेकिन यदि आप नहीं जा रहे हैं तो क्या वास्तव में इसकी आवश्यकता है? क्या यह सिर्फ अच्छा अभ्यास है, जैसे नियम "हमेशा default: आपके switch में" है?

+1

यह वास्तव में एक अच्छा सवाल है। मेरी इच्छा है कि कोई आर्किटेक्चर का वर्णन करके इसका उत्तर देगा जहां va_end नो-ऑप नहीं है। – erikkallen

+1

एफवाईआई: एमएसवीएस 2008 - #define _crt_va_end (एपी) (एपी = (va_list) 0) – Yarik

+0

@erikkallen: "परिभाषित va_end" के लिए एक Google खोज करें और आपको कुछ असामान्य परिभाषाएं मिलेंगी जो अनिवार्य रूप से नो- सेशन। – PlasmaHH

उत्तर

40

va_end सफाई के लिए उपयोग किया जाता है। आप ढेर को तोड़ना नहीं चाहते हैं, है ना?

man va_start से

:

va_end()

va_start से प्रत्येक मंगलाचरण() va_end() एक ही समारोह में के एक इसी मंगलाचरण से मिलान किया जाना चाहिए। कॉल va_end (एपी) के बाद चर एपी अपरिभाषित है। सूची के एकाधिक ट्रैवर्सल, प्रत्येक va_start() और va_end() द्वारा ब्रैकेट किए गए हैं। va_end() एक मैक्रो या एक समारोह हो सकता है।

शब्द की उपस्थिति होना चाहिए।

ढेर दूषित हो सकता है क्योंकि आपको नहीं पता कि va_start() कर रहा है। va_* मैक्रोज़ का मतलब काले बक्से के रूप में किया जाना है। प्रत्येक मंच पर प्रत्येक कंपाइलर जो कुछ भी चाहता है वह कर सकता है। यह कुछ भी नहीं कर सकता है, या यह बहुत कुछ कर सकता है।

कुछ एबीआई रजिस्टरों में पहले कुछ तर्क पास करते हैं, और बाकी स्टैक पर जाते हैं। एक va_arg() और अधिक जटिल हो सकता है। आप देख सकते हैं कि दिए गए कार्यान्वयन में विविधताएं होती हैं, जो दिलचस्प हो सकती हैं, लेकिन पोर्टेबल कोड लिखने में आपको उन्हें अपारदर्शी संचालन के रूप में देखना चाहिए।

+0

क्या इसका मतलब यह है कि सूचक 'वैश्विक' है और जब फ़ंक्शन को रीसेट किए बिना फ़ंक्शन को दूसरी बार कहा जाता है, तो स्टैक दूषित हो जाएगा? – Yarik

+3

यह दूषित हो सकता है क्योंकि * आप नहीं जानते कि va_start() क्या कर रहा है। * यह कुछ भी कर सकता है। और इसे साफ करने की जरूरत है। इसलिए, जब आप va_start() को कॉल करते हैं, तो आपको * va_end() से मेल खाना चाहिए। – greyfade

+0

स्पष्टीकरण के लिए धन्यवाद। – Yarik

10

सामान्य "स्टैक पर पारित पैरामीटर" कार्यान्वयन में, मेरा मानना ​​है कि va_end() आमतौर पर कुछ भी खाली/खाली नहीं होता है। हालांकि, उन प्लेटफॉर्म पर जिनके पास कम पारंपरिक योजनाएं हैं, यह आवश्यक हो जाता है। प्लेटफ़ॉर्म तटस्थ रहने के लिए इसे "अच्छा अभ्यास" है।

+0

यह उस स्थिति में स्टैक को रीसेट कर सकता है जब आपने सभी var_args पर पुनरावृत्ति नहीं की थी। – Spidey

11

लिनक्स x86-64 पर केवल एक ट्रैवर्सल va_list चर पर किया जा सकता है। अधिक ट्रैवर्सल करने के लिए इसे पहले va_copy का उपयोग करके प्रतिलिपि बनाना होगा। man va_copy विवरण बताते हैं:

va_copy()

एक स्पष्ट कार्यान्वयन के लिए होता है एक va_list variadic समारोह के स्टैक फ्रेम करने के लिए एक सूचक हो।इस तरह के एक सेटअप में (अब तक का सबसे सामान्य) वहाँ एक काम के खिलाफ कुछ भी नहीं लगता है

va_list aq = ap; 

दुर्भाग्य से, वहाँ भी कर रहे हैं प्रणाली है कि यह संकेत (लंबाई 1 के) की एक सरणी है, और वहाँ एक

की जरूरत है
va_list aq; 
    *aq = *ap; 

अंत में, सिस्टम जहां तर्क रजिस्टरों में पारित कर रहे हैं, यह va_start() स्मृति को आबंटित करने, वहाँ तर्क की दुकान, है और यह भी एक संकेत है जिनमें से तर्क बगल में है के लिए आवश्यक हो सकता है, ताकि va_arg () कदम कर सकते हैं सूची के माध्यम से। अब va_end() आवंटित स्मृति फिर से मुक्त कर सकते हैं। इस स्थिति को समायोजित करने के लिए, C99) एक मैक्रो va_copy(), तो कि ऊपर काम से

va_list aq; 
    va_copy(aq, ap); 
    ... 
    va_end(aq); 

va_copy से प्रत्येक मंगलाचरण (बदला जा सकता है कहते हैं va_end की इसी invoca- tion से मेल खाना आवश्यक() एक ही समारोह में। कुछ सिस्टम जो va_copy() की आपूर्ति नहीं करते हैं, इसके बजाय __va_copy है, क्योंकि यह नाम ड्राफ्ट प्रस्ताव में उपयोग किया गया था।

+2

इसे क्लियरफ़ी करने के लिए; लिनक्स x86-64 के लिए कुछ खास नहीं है। 'va_copy' की आवश्यकता होती है यदि आप किसी सूची में दो बार फिर से दोहराना चाहते हैं, जब आपके पास केवल' va_list' चर उपलब्ध है। (उदाहरण के लिए 'va_list' को तर्क के रूप में लेने वाले फ़ंक्शन के अंदर)। जितना चाहें आप हमेशा 'va_start' और' va_end' को कॉल कर सकते हैं। –

+0

@MattMcNabb x86-64 'va_list' पर ट्रैवर्सल की स्थिति को बनाए रखता है। X86 पर यह नहीं है। –

+0

@downvoter क्या गलत है? –

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